// src/App.jsx import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; function TodoList() { const queryClient = useQueryClient(); const [text, setText] = useState(""); const { data: todos, isLoading } = useQuery({ queryKey: ["todos"], queryFn: () => fetch("/api/todos").then((r) => r.json()), }); const addTodoMutation = useMutation({ mutationFn: (newTodo) => fetch("/api/todos", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newTodo), }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["todos"] }); }, }); function handleAdd() { addTodoMutation.mutate({ text }); setText(""); } if (isLoading) return

Loading...

; return (
setText(e.target.value)} />
); } function App() { return ; } export default App; /* Notes: - addTodoMutation.mutate() triggers the POST request; onSuccess then calls invalidateQueries on ["todos"], which is the SAME key the list above is using. - That invalidation causes useQuery's ["todos"] data to refetch automatically — the new todo appears in the list without any manual setTodos call or local state update written by hand. */