React Query - Keys & Prefetching

Full Stack Developer and JavaScript and TypeScript enthusiastic.
Search for a command to run...

Full Stack Developer and JavaScript and TypeScript enthusiastic.
No comments yet. Be the first to comment.
Hey Folks, Sometimes to improve the user experience you can decide to bet on the success of your code, so you can assume that the code will go in the right way to make your application faster in the eyes of your users. This approach is called Optimis...
Today, I wanna show you how to set up your devices with Antigravity using only the agentic mode, without touching any code. At the last CodeMotion Rome, I got my special badge. A CM Node, a special ha

As a developer, you have to take control of your projects every day. Whether it is a company repository, an open source project you maintain or collaborate on, or a simple pet project. Gaining control over your projects often depends on the platform ...

My Antigravity first experience

Write clear and insightful commit messages using AI and GitLens.

We are in the AI era. New models emerge daily, and many applications have already integrated AI into their workflows. Gemini, OpenAI, Copilot, Deepseek, Llama, and many others enable AI in your applications or help you write code, but they all need a...

Hey Folks, Today I want to share two important things if you are using ReactQuery. The first is how the keys are composed, and the second is how to prefetch data to reduce the user's wasted time. So let's start 🚀
As you have already learned in this series, React query uses the keys to save the data of a specific API. And these keys must be unique for each specific API. When you create a useQuery hook, the first parameter is the query's key, which is an array. This array is used to compose the key, and it is in charge of you creating the key in the right way for your case. As said before, the key is an array, and in this way, you can create a key composed of different data.
So, for instance, you can have a key for the list of the todos and a key for the detail of a specific todo (["todos"] and ["todo", 2].)
As you can notice, you can put in the key whatever you want, string number or boolean; it is completely on your side; the important thing you must remember every time is that each key must be unique. This concept, and the key you choose, are also important if you want to prefetch the data because you must use the same key to save the data prefetched in the react query state.
In some scenarios, loading the data before the user asks for it could be interesting. This improves the user experience and reduces the waste time for them. But how can you do that with react query?
First, you need to use the QueryClient object that exposes the prefetchQuery method.
This method accepts two parameters: the query's key and the fetch request.
In this way, you can handle a simple but powerful prefetching flow with few lines of code. Let's take a look at this example
export const useTodos = (): UseTodos => {
const client = useQueryClient();
const [userFilter, setUserFilter] = useState<number | null>(null);
const filterTodoByAssignee = useCallback(
(todos: Todo[]) => {
if (!userFilter) return todos;
return todos.filter((todo) => todo.assigneeId === userFilter);
},
[userFilter]
);
const {
data: todos = [],
isLoading,
isFetching,
error,
} = useQuery([QUERY_KEY.todos], fetchTodos, {
refetchOnWindowFocus: false,
retry: 2,
select: filterTodoByAssignee,
onSuccess: (data) => {
data.forEach((todo) => {
client.prefetchQuery([QUERY_KEY.todos, id], () => fetchTodo(id));
});
},
});
return {
todos,
isLoading,
isFetching,
error: mapError(error),
setUserFilter,
};
};
As you can notice, in this example in the onSuccess hook, the prefetch feature starts to load the data of every todo in the result of the list. That allows React Query to save the data in the storage and reuse them in the future when the application asks for that data. For instance, in a todo detail hook like this
const fetchTodo = async (id: Todo['id']): Promise<Todo> => {
const response = await fetch(`api/tasks/${id}`);
if (!response.ok) {
throw new ResponseError(`Failed to fetch todo with id ${id}`, response);
}
return await response.json();
};
export const useGetTodoById = (id: Todo['id']): UseTodo => {
const {
data: todo = null,
isLoading,
error,
} = useQuery([QUERY_KEY.todos, id], () => fetchTodo(id), {
refetchOnMount: false,
refetchOnWindowFocus: false,
retry: 2,
});
return {
todo,
isLoading,
error: mapError(error),
};
};
As you can see, the key of this useQuery is the same as the key in the prefetch example, and in this way, ReactQuery is able to understand if the data are already loaded or not.
As you can imagine, with this simple feature, you can improve the quality of your application and maybe prefetch some data that could take too long to load.
Ok, I think you have a great idea of how key and prefetching work in React Query.
To learn more about them, check out also my Youtube video available here 👇
I think that’s all from this article; I hope you enjoyed this content!
See you soon folks
Bye Bye 👋
p.s. you can find the code of the video here