Managing Async State with Tanstack Query
There are many ways of managing async (server) state in a React application. We will be using a library called Tanstack Query (formerly known as React Query). Tanstack Query is a powerful library that helps you fetch, cache, and update data in your React applications without having to touch the global state.
Key Concepts of Tanstack Query:
Fetching and Caching: Tanstack Query automatically fetches data from APIs and caches the results to optimize performance and reduce unnecessary network requests.
Background Updates: It refetches data in the background when there are changes, ensuring that your UI is always up-to-date.
Error Handling: Tanstack Query provides built-in mechanisms for error handling and loading state management.
Devtools: It comes with devtools that allow you to inspect the cache and see what queries are running, which can be very helpful for debugging.
Basic Usage:
To use Tanstack Query, you'll typically use the useQuery
hook, which allows you to fetch data from an API and access the data, loading state, and error state inside your component.
Here's a simple code example that demonstrates how you can use Tanstack Query to fetch a list of todos dfrom a server:
import { useQuery } from '@tanstack/react-query'import request from 'superagent'interface Todo {userId: numberid: numbertitle: stringcompleted: boolean}// This is a function that fetches data from an API endpointconst fetchTodos = async () => {try {const response = await request.get('https://jsonplaceholder.typicode.com/todos')return response.body as Todo[]} catch (error) {throw new Error('Network response was not ok')}}// This is our React component that uses the useQuery hook to fetch datafunction Todos() {const { data, isPending, isError, error } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos });// Render UI for loading states or errorsif (isPending) {return <div>Loading...</div>}if (isError) {return <div>Error: {error.message}</div>;}// Render the UI based on the fetched datareturn (<div><h1>Todos</h1><ul>{data.map((todo) => (<li key={todo.id}>{todo.title}</li>))}</ul></div>)}export default Todos;
In this example, useQuery
is used to fetch a list of todos from a fake REST API (jsonplaceholder.typicode.com
). The hook returns an object containing data
, isPending
, isError
, and error
. Inside the component, we handle the loading state by checking isPending
and displaying a loading message. If there's an error, we check isError
and display the error message. Finally, we render the todos using the data returned from the API.
Note: isPending
is used from v5 of Tanstack Query. Older versions used isLoading
To get started with Tanstack Query in a React project, you'll need to set up a QueryClient
and a QueryClientProvider
at the root of your application to provide the context for your queries:
import { createRoot } from 'react-dom/client'import { QueryClient, QueryClientProvider } from '@tanstack/react-query'import App from './App'const queryClient = new QueryClient()createRoot(document.getElementById('root') as HTMLElement).render(<QueryClientProvider client={queryClient}><App /></QueryClientProvider>)
This setup allows you to use Tanstack Query throughout your application. Remember to install Tanstack Query before importing it into your project:
npm install @tanstack/react-query
And that's a basic introduction to using Tanstack Query in a React app to manage server state. It abstracts away many of the complexities of data fetching and caching, allowing you to focus on building your UI.