I am having issues understanding how to getuseLazyQuery to get the cached data on a second time the component is mounted.
Imagine the following:
... const [trigger, { data }] = api.useLazyQuery(); // assume it takes 10 seconds to run const exists: boolean = !!data; const onClickHandler = (e) => { trigger(e.target.value) }; // handler for a button that takes an argument React.useEffect(() => { console.log(data); // it shows undefined }, [data]); return <>{exists && <>Result data: {data}</>}</>...So basically, the first time the component is mounted, the user clicks a button to trigger the run ofapi.useLazyQuery(), get the data and show the results after 10 seconds. Good.
Now on the second time the component is mounted, it should just simply show the data. It doesn't becausedata is undefined. But if the user clicks the button, it shows the results right away, it didn't wait for those 10 seconds. This means that the data was returned from the store/cache.
So how do I go about doing this so that I can immediately show the data after the second time the component is mounted, without having the user clicking the button just to trigger thetrigger function?
Edit: updating the example to reflect the fact thattrigger takes an input parameter. There is a proposal to usefixedCacheKey but that essentially keeps the same cache for the same endpoint, regardless of the input argument.
I am also open to other solutions if there is no way around the rtk.
- This is normal, isn't it? When a user action triggers a data query – whether fetching from the server or retrieving cached data – the component naturally reinitializes. If you want the component to retain its state when revisited (preserving its appearance from the first exit), you should cache the component.yuanyxh– yuanyxh2025-03-08 03:54:15 +00:00CommentedMar 8 at 3:54
1 Answer1
Issue
The issue you are observing is due to the fact that when the component remounts it is getting a new "instance" of the lazy query hook and trigger function. The query endpoint data is cached in the store, but the subscription is cleared when the component unmounts, or rather, a new subscription will be created the first time the trigger function is called. This is when the subscription and cached data are coupled.
Solution Suggestion
- You can accept this as the default expected behavior of query endpoints and lazy hooks and be done with it and move on.
- You can use a mutation endpoint and a fixed cache key so any cached data will be immediately available to any consumers.
Example:
Update from abuilder.query tobuilder.mutation endpoint definition:
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";export const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: "https://jsonplaceholder.typicode.com/", }), endpoints: (build) => ({ getPosts: build.mutation({ // <-- mutation query: () => "posts", }), }),});export const { useGetPostsMutation } = api;Call the mutation hooks and provide afixedCacheKey value so all instances of that hook will access the same cached endpoint data.
import { useGetPostsMutation } from "./api.slice";import { useEffect, useState } from "react";const Component = () => { const [trigger, { data }] = useGetPostsMutation({ fixedCacheKey: "keep" // * }); useEffect(() => { console.log({ data }); }, [data]); const clickHandler = () => { trigger(); }; return ( <> <button type="button" onClick={clickHandler}> Trigger Query </button> <div>Data: {....data...}</div> </> );};*Note: I used"keep", but any sufficiently unique cache key value can be used.
Demo
10 Comments
id. So I calltrigger(1) and I get{data: 1}. Now if I calltrigger(2) on a second component mount, I will still get{data: 1} as a response (I would expect2 instead). Any ideas for that case?{ fixedCacheKey: "keep-" + id }. Example sandbox fork:codesandbox.io/p/devbox/….useQueryState like I shared on that exampleExplore related questions
See similar questions with these tags.


