Data fetching
Server side data fetching in Fresh is accomplished through asynchronous handler
functions. These handler functions can call a ctx.render() function with the
data to be rendered as an argument. This data can then be retrieved by the page
component through the data property on the props.
Here is an example:
interface Project {
name: string;
stars: number;
}
export const handler: Handlers<Project> = {
async GET(_req, ctx) {
const project = await db.projects.findOne({ id: ctx.params.id });
if (!project) {
return ctx.renderNotFound({
message: "Project does not exist",
});
}
return ctx.render(project);
},
};
export default function ProjectPage(props: PageProps<Project>) {
return (
<div>
<h1>{props.data.name}</h1>
<p>{props.data.stars} stars</p>
</div>
);
}The type parameter on the PageProps, Handlers, Handler, and FreshContext
can be used to enforce a TypeScript type to use for the render data. Fresh
enforces during type checking that the types in all of these fields are
compatible within a single page.
Asynchronous routes
As a shortcut for combining a GET handler with a route, you can define your
route as async. An async route (a route that returns a promise) will be
called with the Request and a RouteContext (similar to a HandlerContext).
Here is the above example rewritten using this shortcut:
interface Project {
name: string;
stars: number;
}
export default async function ProjectPage(_req, ctx: FreshContext) {
const project: Project | null = await db.projects.findOne({
id: ctx.params.id,
});
if (!project) {
return <h1>Project not found</h1>;
}
return (
<div>
<h1>{project.name}</h1>
<p>{project.stars} stars</p>
</div>
);
}