Overview: TanStack / React Query
Overview: TanStack / React Query
React Query (recently renamed to TanStack query) is a data-fetching library that makes fetching, caching, synchronizing, and updating server state in your web applications a breeze.
The state management libraries like Redux, Recoil, and Zustand are great for working with client state, they are not so great at working with async or server state. This is because the server state is different.
Server state:
- Is persisted remotely in a location you do not control or own
- Requires asynchronous APIs for fetching and updating
- Implies shared ownership and can be changed by other people without your knowledge
- Can potentially become “out of date” in your applications if you’re not careful
Once you grasp the nature of the server state in your application, even more challenges will arise as you go, for example:
- Caching… (possibly the hardest thing to do in programming)
- Deduping multiple requests for the same data into a single request
- Updating “out of date” data in the background
- Performance optimizations like pagination and lazy loading of data
- Managing memory and garbage collection of server state
Coding examples
- Using react query the pain of handling state updation is taken care by the useQuery hook
- It also reduces the number of lines in a component if the component deals with multiple API calls
Without React Query
import React, {useState, useEffect } from "react";
import axios from 'axios'
const TodoList = () => {
const [todos, setTodos] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() =>
const fetchTodos = async () => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/todos"
);
setTodos (response.data);
} catch (error) {
console.error("Error fetching todos:", error);
} finally {
setLoading(false);
}
}
fetchTodos();
},[])
return {...};
export default TodoList;
With React-Query
import React, {useState, useEffect } from "react";
import axios from 'axios'
import {useQuery} from 'react-query';
const fetchTodos = async () => {
return (await axios.get(
"https://jsonplaceholder.typicode.com/todos"
)).data.todos;
}
const TodoList = () => {
const {data:todos=[], isLoading:loading}=useQuery({queryKey:['todos'],queryFn:fetchTodos})
return {...};
export default TodoList
As you can see from the above code using useQuery hook from react-query we were able to avoid setting the state from the API response into react state and also loading state logic
Apart from the coding optimizations and other loading utilities, the main thing of react query is the caching of API response which can effectively improve the performance of a page
Here in the below picture, it shows how it caches the data under the hood
Apart from this useQuery API there is another hook called useMutation API which is to perform the mutations on the server like we do with HTTP post, put and delete method
The main advantage of react query
- Caching
- Pagination and Infinite scrolling
- Optimistic updates
- SSR support
- Background indicators
- Also Supports other frameworks
- Upto v3: only react
- From v4 (rebranded to @tanstack): Vue, Svelte, Solid
- Currently v5: Experimental Angular
Problems we faced while using react-query
- Doesn’t support caching of batch requests
Batching is generally we fetch the multiple request data in a single api call, like if we have to fetch the users data with user id 1,2,3 instead of performing 3 api calls we do in one.
The way react-query cache works is that when we perform one API call containing a batch of request IDs it saves the query containing the request id’s in an array structure.
The next time, we perform another batch that contains request id’s from the previous batch it doesn’t optimize and sends only the request that doesn’t have data for the request id’s
So we solved this problem using the dataloader(from GraphQL community) on top of react-query
Note: Both react-query and dataloader have caches so we need to disable dataloader’s cache and let react-query manage it all. That way we get de-duplication and caching from react-query and batching from data loader
Conclusion: The react-query is a great tool for caching and other API-related utilities if your website already doesn’t deal with all of the above-related queries.