How to use TanStack Query (react-query) with Gatsby
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.