Welcome back! In this part, we'll demonstrate how to integrate the api-def package with a Next.js application for client-side and server-side API fetching using Tanstack Query.
Recap:
- We explored the concept and implementation of the
api-defpackage.
Integration with Tanstack Query:
-
Configure Tanstack Client:
- Create a
Providerscomponent to manage the QueryClient instance. - Use
isServerfrom@tanstack/react-queryto create separate clients for server and client.
- Create a
import { QueryClient, QueryClientProvider, isServer } from "@tanstack/react-query";
function makeQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000, // Cache timeout in milliseconds
},
},
});
}
let browserQueryClient: QueryClient | undefined = undefined;
function getQueryClient() {
if (isServer) {
return makeQueryClient();
} else {
if (!browserQueryClient) {
browserQueryClient = makeQueryClient();
}
return browserQueryClient;
}
}
export function Providers({ children }: { children: React.Node }) {
const queryClient = getQueryClient();
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}
-
Provider Placement:
- Wrap your application with the
Providerscomponent at the root level (e.g., inlayout.tsx) to make the QueryClient context globally accessible.
- Wrap your application with the
import { Providers } from "./providers";
export default function RootLayout({ children }: { children: React.Node }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
-
Client-Side Fetching:
- Create a component (e.g.,
Userscomponent) that utilizes theuseQueryhook from Tanstack Query. - Use the
GetUserKeysfunction fromapi-defto define the query key for caching and invalidation. - Use the
ApiClientfromapi-defwithin thequeryFnto fetch data from the API.
- Create a component (e.g.,
import { GetUserKeys, ApiClient } from "@repo/api-definitions";
import { useQuery } from "@tanstack/react-query";
export function Users() {
const { data } = useQuery({
queryKey: GetUserKeys.getUsers({}),
queryFn: async ({ queryKey }) => {
const queries = queryKey[0]?.requestBody;
return ApiClient.getUsers(queries || {});
},
});
return <>{JSON.stringify(data)}</>;
}
-
Server-Side Prefetching:
- Within a server component (e.g., in
page.tsx), prefetch the data usingqueryClient.prefetchQuerybefore rendering the component. - Use the same
GetUserKeysandApiClientfromapi-defwithin thequeryFnfor consistency. - Wrap the component with a
HydrationBoundaryfrom Tanstack Query to hydrate the prefetched data on the client.
- Within a server component (e.g., in
import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query";
import { GetUserKeys, ApiClient } from "@repo/api-definitions";
import { Users } from "@app/user/users";
export default async function PostsPage() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery({
queryKey: GetUserKeys.getUsers({}),
queryFn: ({ queryKey: [requestBody] }) => {
return ApiClient.getUsers(requestBody?.requestBody || {});
},
});
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<Users />
</HydrationBoundary>
);
}
Benefits:
- Type safety: Zod ensures type safety throughout the API interactions.
-
Centralized definitions:
api-defoffers a single source for API definitions and endpoints. - Efficient caching: Tanstack Query manages caching and invalidation for optimized performance.
Next Steps:
In the upcoming post, we'll delve into the integration of another powerful tool: React Hook Form. This library will help us streamline form handling, validation, and submission processes within our React applications.
Stay tuned!
Footnote: This implementation is inspired by the Tanstack Query documentation on Advanced Server-Side Rendering: Advanced Server Rendering
Top comments (0)