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)