By Paul Scanlon

How to use TanStack Query (react-query) with Gatsby

  • Gatsby
  • Gatsby Serverless Functions
  • React
  • JavaScript
  • React Query

In this post I’ll be discussing how to use TanStack Query, or more specifically @tanstack/react-query to replace the often quite cumbersome approach of using a useEffect to make HTTP requests to API’s and others services.

But first. Here’s Tanner Linsley, give them a follow, so much good stuff coming out of the @tan_stack!

useEffect

Here’s a reasonably common approach when using a useEffect “onMount” to make a request. There’s two useState values; one for the loading status, and one for the response.

The response in this example is stringified and returned in Jsx wrapped in an HTML <pre>.

// src/pages/test.js

import React, { useState, useEffect } from 'react';

const Page = () => {
  const [response, setResponse] = useState(null);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const getTestData = async () => {
      setIsLoading(true);

      try {
        const response = await (await fetch('https://paulieapi.gatsbyjs.io/api/v2/test')).json();
        setResponse(response);
        setIsLoading(false);
      } catch (error) {
        setResponse(error);
        setIsLoading(false);
      }
    };

    getTestData();
  }, []);

  return <div>{isLoading ? <div>Loading</div> : response ? <pre>{JSON.stringify(response, null, 2)}</pre> : null}</div>;
};

export default Page;

Installation

npm install @tanstack/react-query
# or
yarn add @tanstack/react-query

QueryClient & Provider

Quoting from the docs.

Use the QueryClientProvider component to connect and provide a QueryClient to your application:

The QueryClient is what’s used for making requests. This needs to be made globally available to your Gatsby site. You can achieve this usings Gatsby’s wrapRootElement.

When using wrapRootElement it’s advisable to implement the same functionality in both gatsby-browser.js and gatsby-ssr.js.

Rather than duplicating code I prefer to create a shared, or common component that can be used by both gatsby-browser.js and gatsby-ssr.js.

Shared Component

Create a new component called root-element.js and add the following.

// src/components/root-element.js

import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

const RootElement = ({ children }) => {
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
};

export default RootElement;

gatsby-browser.js

// gatsby-browser.js

import React from 'react';
import RootElement from './src/components/root-element';

export const wrapRootElement = ({ element }) => {
  return <RootElement>{element}</RootElement>;
};

gatsby-ssr.js

// gatsby-ssr.js

import React from 'react';
import RootElement from './src/components/root-element';

export const wrapRootElement = ({ element }) => {
  return <RootElement>{element}</RootElement>;
};

Using both gatsby-browser.js and gatsby-ssr.js will ensure this functionality works during development, and when the production build is created.

useQuery

Now you can replace all the useEffect and useState code mentioned above with the following.

// src/pages/test.js

+ import React from 'react';
- import React, { useState, useEffect } from 'react';
+ import { useQuery } from '@tanstack/react-query';

 const Page = () => {
-  const [response, setResponse] = useState(null);
-  const [isLoading, setIsLoading] = useState(false);

-  useEffect(() => {
-    const getTestData = async () => {
-      setIsLoading(true);

-      try {
-        const response = await (await fetch('https://paulieapi.gatsbyjs.io/api/v2/test')).json();
-        setResponse(response);
-        setIsLoading(false);
-      } catch (error) {
-        setResponse(error);
-        setIsLoading(false);
-      }
-    };

-    getTestData();
-  }, []);

+  const response = useQuery(['response'], async () => {
+    return await (await fetch('https://paulieapi.gatsbyjs.io/api/v2/test')).json();
+  });

  return (
    <div>
-     {isLoading ? <div>Loading</div> : response ? <pre>{JSON.stringify(response, null, 2)}</pre> : null}
+     {response.isLoading ? <div>Loading</div> : response ? <pre>{JSON.stringify(response.data, null, 2)}</pre> : null}
    </div>
  );
};

export default Page;

There’s so much more you can do with TanStack Query, so take a look around the docs. Everything is clearly explained and petty much all of the Guides & Concepts have example code snippets.

Hey!

Leave a reaction and let me know how I'm doing.

  • 0
  • 0
  • 0
  • 0
  • 0
Powered byNeon