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

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series