DEV Community

Santhanam Elumalai
Santhanam Elumalai

Posted on

Building a Robust API Layer - `api-def` Package Integration with React (NextJs) app

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:

  1. 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.
  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>;
  }
Enter fullscreen mode Exit fullscreen mode
  1. Provider Placement:
    • Wrap your application with the Providers component at the root level (e.g., in layout.tsx) to make the QueryClient context globally accessible.
  import { Providers } from "./providers";

  export default function RootLayout({ children }: { children: React.Node }) {
      return (
          <html lang="en">
              <body>
                  <Providers>{children}</Providers>
              </body>
          </html>
      );
  }
Enter fullscreen mode Exit fullscreen mode
  1. Client-Side Fetching:
    • Create a component (e.g., Users component) that utilizes the useQuery hook from Tanstack Query.
    • Use the GetUserKeys function from api-def to define the query key for caching and invalidation.
    • Use the ApiClient from api-def within the queryFn to fetch data from the API.
  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)}</>;
  }
Enter fullscreen mode Exit fullscreen mode
  1. Server-Side Prefetching:
    • Within a server component (e.g., in page.tsx), prefetch the data using queryClient.prefetchQuery before rendering the component.
    • Use the same GetUserKeys and ApiClient from api-def within the queryFn for consistency.
    • Wrap the component with a HydrationBoundary from Tanstack Query to hydrate the prefetched data on the client.
  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>
      );
  }
Enter fullscreen mode Exit fullscreen mode

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!

Github PR Location

Footnote: This implementation is inspired by the Tanstack Query documentation on Advanced Server-Side Rendering: Advanced Server Rendering

Top comments (0)