#
Fetch page data
There are several approaches to fetching data for pages. We prefer using a backend-for-frontend (BFF) with a dedicated endpoint for each page, returning a data structure tailored to that page. We rely on server state as our single source and TanStack Query is used to handle data fetching and caching.
#
Fetch data
👉 There are two key steps to fetch page data:
- Fetch the data using the useSuspenseQuery hook.
- Define a fallback element in the layout component using the Suspense component
Refer to the create a local module guide as a starting point and update both the module and its Page component to fetch data:
import { useSuspenseQuery } from "@tanstack/react-query";
interface Character {
name: string;
species: string;
}
export function Page() {
const { data: characters } = useSuspenseQuery({ queryKey: ["/api/characters"], queryFn: () => {
const response = await fetch("/api/characters");
return await response.json();
}});
return (
<div>
{characters.map((x: Character) => {
return (
<div key={x.name}>
<span>Name: {x.name}</span>
<span>Species: {x.species}</span>
</div>
);
})}
</div>
);
}
import { Suspense } from "react";
import { Outlet } from "react-router";
export function RootLayout() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Outlet />
</Suspense>
);
}
First, define an MSW request handler that returns the number of times it has been fetched:
import { HttpResponse, http, type HttpHandler } from "msw";
export const requestHandlers: HttpHandler[] = [
http.get("/api/characters", () => {
return HttpResponse.json([{
"name": "Rick Sanchez",
"species": "Human"
}, {
"name": "Morty Smith",
"species": "Human"
}]);
})
];
Then, register the request handler using the module registration function:
import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly";
export const register: ModuleRegisterFunction<FireflyRuntime> = async runtime => {
if (runtime.isMswEnabled) {
// Files that includes an import to the "msw" package are included dynamically to prevent adding
// unused MSW code to the production bundles.
const requestHandlers = (await import("../mocks/handlers.ts")).requestHandlers;
runtime.registerRequestHandlers(requestHandlers);
}
}
#
Handle fetch errors
Refer to the define error boundaries essential page.
#
Setup TanStack Query
Refer to the setup TanStack Query integration guide.