きっかけ
useMutation
したタイミングで、invalidateQueries
を利用して、関連するクエリを再実行し状態を更新しようとしたところ、全然できず詰まってしまった。
このスレに救われたので、ここに載っていた間違い集をまとめておく。
確認した方が良いところ
1. 複数のQueryCleintインスタンスを作成していないか
基本的にQueryClientのインスタンスはアプリケーションライフサイクルにおいて、一つだけ作成すべき。
誤って複数のQueryCleintインスタンスを作成していないか確認しよう。
NG例 ❌
/* eslint "@tanstack/query/stable-query-client": "error" */
function App() {
const queryClient = new QueryClient()
return (
<QueryClientProvider client={queryClient}>
<Home />
</QueryClientProvider>
)
}
OK例1 ⭕️
function App() {
const [queryClient] = useState(() => new QueryClient())
return (
<QueryClientProvider client={queryClient}>
<Home />
</QueryClientProvider>
)
}
OK例2 ⭕️
const queryClient = new QueryClient()
function App() {
return (
<QueryClientProvider client={queryClient}>
<Home />
</QueryClientProvider>
)
}
OK例3 ⭕️
async function App() {
const queryClient = new QueryClient()
await queryClient.prefetchQuery(options)
}
2. enabled
オプションがfalse
になっているクエリに対しては、invalidateQueries
やrefetchQueries
は使えない
それはそうという感じだが、一応確認しておこう。
NG例 ❌
function Todos() {
const { data, isFetching } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
// enabled=falseのクエリは、invalidateQueries()やrefetchQueries()の影響を受けない
enabled: false,
})
return (...)
}
3. QueryClientインスタンスへのアクセスはuseQueryClient
を使う
QueryClientProvider
を利用している場合は、useQueryClient
フックを利用してQueryClientインスタンスにアクセスしよう。
NG例 ❌
const createTodoMutation = useMutation(postTodo, {
onSuccess: async () => {
const queryClient = new QueryClient();
await queryClient.invalidateQueries("todos");
},
});
OK例 ⭕️
import { useQueryClient } from '@tanstack/react-query'
const queryClient = useQueryClient()
const createTodoMutation = useMutation(postTodo, {
onSuccess: async () => {
await queryClient.invalidateQueries("todos");
},
});
4. queryKey
が誤っている
invalidateQueries
やrefetchQueries
に渡しているqueryKey
が誤っていないか確認しよう。
5. invalidateQueries
やrefetchQueries
が実行される前に画面遷移したり、コンポーネントをアンマウントしてしまっている
NG例 ❌
import { useQueryClient } from '@tanstack/react-query'
const queryClient = useQueryClient()
const createTodoMutation = useMutation(postTodo, {
onSuccess: async () => {
// ここで画面遷移してしまうと、後続の処理が実行されない
// コンポーネントのアンマウントも同様(ダイアログの開閉など要注意)
router.push("/todos")
await queryClient.invalidateQueries("todos");
},
});
6. invalidateQueries
しようとしているクエリがinactive
である
invalidateQueries
は、デフォルトだとactive
なクエリのみをinvalidateするため、
クエリがinactive
な状態である場合(画面遷移した時やコンポーネントがアンマウントされた場合など)は、対象に含まれない。
inactive
なものも対象に含める場合は、refetchType
オプションを利用する必要がある。