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-def
package.
Integration with Tanstack Query:
-
Configure Tanstack Client:
- Create a
Providers
component to manage the QueryClient instance. - Use
isServer
from@tanstack/react-query
to 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
Providers
component 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.,
Users
component) that utilizes theuseQuery
hook from Tanstack Query. - Use the
GetUserKeys
function fromapi-def
to define the query key for caching and invalidation. - Use the
ApiClient
fromapi-def
within thequeryFn
to 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.prefetchQuery
before rendering the component. - Use the same
GetUserKeys
andApiClient
fromapi-def
within thequeryFn
for consistency. - Wrap the component with a
HydrationBoundary
from 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-def
offers 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)