Invalidating Queries with QueryKeys

Exemplify the process of invalidating and refetching data using QueryKeys after a mutation operation.
import { useQuery, useQueryClient, useMutation } from 'react-query';

// Fetch function that gets data based on the todoId
const fetchTodo = async (todoId) => {
    const response = await fetch(`/api/todos/${todoId}`);
    if (!response.ok) {
        throw new Error('Network response was not ok');
    return response.json();
This is the setup for fetching a todo item using its ID. It involves defining an asynchronous fetch function that will be used by the useQuery hook to fetch data.
const Todo = ({ todoId }) => {
    const queryClient = useQueryClient();
    const { data: todo, isError, error } = useQuery(['todos', todoId], () => fetchTodo(todoId));

    if (isError) return <div>Error: {error.message}</div>;
    if (!todo) return <div>Loading...</div>;

    return <div>{todo.title}</div>;
This component makes use of the useQuery hook to fetch a todo item. It queries for a specific todo based on its ID and returns error or loading states accordingly.
const updateTodo = async ({ todoId, newValues }) => {
    const response = await fetch(`/api/todos/${todoId}`, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json',
        body: JSON.stringify(newValues),
    return response.json();
Defines an async function for updating a todo item. It sends a PUT request to the server with the new todo values.
const useUpdateTodo = () => {
    const queryClient = useQueryClient();
    return useMutation(updateTodo, {
        onSuccess: () => {
            // Invalidate and refetch
This custom hook uses useMutation for the update operation. It invalidates all queries with the 'todos' key upon success, causing re-fetching of todo data.