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