Ooker
Ooker12mo ago

How does form submission work?

I'm following the tutorial: https://fresh.deno.dev/docs/getting-started/form-submissions It says:
When the user submits the form, the browser will navigate to /search with the query set as the q query parameter in the URL. The GET handler will then filter the names array based on the query, and pass it to the page component for rendering.
Form submissions | Fresh docs
Robustly handle user inputs using HTML `` elements client side, and form submission handlers server side.
15 Replies
Ooker
OokerOP12mo ago
Is the navigation to /search necessary? Is it correct that the handler can only work with the URL? Or is it a way to avoid having to use island? what is the GET(req, ctx) mean? It seems to be a function, but it isn't imported from anywhere. I search for it but there is no document for it as well
marvinh.
marvinh.12mo ago
The way forms work on the web is that submission triggers a navigation request. Can you share more about what you're trying to build? Handlers in Fresh are part of the routing mechanism. They are called before the component function is called. Typically they are used to pull data from a database or another API. They can be thought of as a middleware to the current route.
export const handler = {
async GET(req, ctx) {
const data = await loadData();
// This triggers HTML rendering
return ctx.render(data);
}
}

export default function MyPage(props) {
return <h1>{props.data.name}</h1>
}
export const handler = {
async GET(req, ctx) {
const data = await loadData();
// This triggers HTML rendering
return ctx.render(data);
}
}

export default function MyPage(props) {
return <h1>{props.data.name}</h1>
}
If no handler export is present, Fresh will add a default one that looks like this behind the scenes:
export const handler = {
GET: (req, ctx) => ctx.render()
}
export const handler = {
GET: (req, ctx) => ctx.render()
}
Since Fresh 1.4 we also support combining the two into a single construct:
export default defineRoute(async (req, ctx) => {
const data = await loadDataFromSomewhere();

return <h1>{data.name}</h1>
});
export default defineRoute(async (req, ctx) => {
const data = await loadDataFromSomewhere();

return <h1>{data.name}</h1>
});
Ooker
OokerOP12mo ago
I just want to dissect the code in the tutorial so I get that handler can only work with URL? also, what is the nature of GET? Is it a function or something?
Fifth-Normal-Form
GET is an HTTP Request Method type. In simple words, the GET method is used to retrieve whatever information is identified by the Request-URL.
Ooker
OokerOP12mo ago
How to use it in JS? MDN doesn't explain anything https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
MDN Web Docs
GET - HTTP | MDN
The HTTP GET method requests a representation of the specified resource. Requests using GET should only be used to request data (they shouldn't include data).
Ooker
OokerOP12mo ago
Handlers in Fresh are part of the routing mechanism
So any handler will navigate to a location? Is this only a thing in Fresh or in any web framework?
marvinh.
marvinh.12mo ago
The handlers concept is specific to the Fresh framework and not something available in the web in general. A similar pattern can be found in other frameworks though. Basically, when a request comes in, folks typically want to respond differently to a GET, a POST or another request type. So instead of having to manually write if statements to check the HTTP verb, Fresh allows you to export an object with the object keys as a shorthand. No, handlers don't navigate you anywhere. When a request comes in they are called. That's it. What you do inside of them is up to you. Let's say you have a file routes/about.tsx. If you add a handler export inside that file it will be called before rendering. That's all there is to it I think you're mixing up HTML forms with Fresh handlers. An HTML form submission by default triggers a navigation request. That happens in the browser, not on the server in Fresh
Ooker
OokerOP12mo ago
so the GET(req, ctx) is not a proper function nor a legit JS syntax but a shorthand syntax that only Deno can understand and translate to a proper function at compile time? In your example, the props object for the MyPage() component is different to the data object, which is the result of the handler. However, in the example of the form submission, the code is:
export const handler: Handlers<Data> = {
GET(req, ctx) {
const url = new URL(req.url);
const query = url.searchParams.get("q") || "";
const results = NAMES.filter((name) => query.includes(name));
return ctx.render({ results, query });
},
};

export default function Page({ data }: PageProps<Data>) {
const { results, query } = data;
export const handler: Handlers<Data> = {
GET(req, ctx) {
const url = new URL(req.url);
const query = url.searchParams.get("q") || "";
const results = NAMES.filter((name) => query.includes(name));
return ctx.render({ results, query });
},
};

export default function Page({ data }: PageProps<Data>) {
const { results, query } = data;
Where does the {data} for the component come from? Surely Fresh must construct it from the result of the handler behind the scene, right? But then, how does it make sure that it'll be correct?
If no handler export is present, Fresh will add a default one that looks like this behind the scenes:
export const handler = {
GET: (req, ctx) => ctx.render()
}
export const handler = {
GET: (req, ctx) => ctx.render()
}
If so, then isn't that the handler always triggers HTML rendering?
marvinh.
marvinh.12mo ago
This is standard JS syntax, nothing Deno specific. This code works as is in any JS engine.
const foo = {
bar() {}
}

// is the same as
const foo = {
bar: () => {}
}
const foo = {
bar() {}
}

// is the same as
const foo = {
bar: () => {}
}
Fresh takes whatever you pass into ctx.render(arg) and sets it on props.data. There is no code to ensure that it is correct or anything. It just passes it along. If nothing is passed to ctx.render() then props.data will be undefined yes
Ooker
OokerOP12mo ago
If so, where can I search for these functions? It not even need to be imported, so it must be a native function. However MDN doesn't explain anything https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET
MDN Web Docs
GET - HTTP | MDN
The HTTP GET method requests a representation of the specified resource. Requests using GET should only be used to request data (they shouldn't include data).
marvinh.
marvinh.12mo ago
The functions are Fresh specific, but the syntax is standard JS. Under the hood Fresh basically does this:
const handler = {
GET(req, ctx) {}
}

Deno.serve((req) => {
const ctx = {}

// Call handler with HTTP verb if present
if (req.method in handler) {
handler[method](req, ctx)
}
})
const handler = {
GET(req, ctx) {}
}

Deno.serve((req) => {
const ctx = {}

// Call handler with HTTP verb if present
if (req.method in handler) {
handler[method](req, ctx)
}
})
It's a basic object key lookup nothing more
Ooker
OokerOP12mo ago
Is there any docs about this?
marvinh.
marvinh.12mo ago
Ooker
OokerOP12mo ago
in that page, I see that req and ctx have prefix underscore. What does this mean?
marvinh.
marvinh.12mo ago
If the variable is unused, the linter will complain by default. The underscore in front of the variable name is a hint to the linter that this is intended so that it doesn't warn. This behavior is similar to rust

Did you find this page helpful?