1

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.

askedMar 7 at 22:09
renatodamas's user avatar
1
  • 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.CommentedMar 8 at 3:54

1 Answer1

1

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

  1. You can accept this as the default expected behavior of query endpoints and lazy hooks and be done with it and move on.
  2. 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

Edit condescending-brattain

answeredMar 8 at 6:58
Drew Reese's user avatar
Sign up to request clarification or add additional context in comments.

10 Comments

Appreciate the help :) but now imagine that trigger receives some input. Like someid. 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?
Would you recommend storing the result in the store manually?
@renatodamas You could incorporate the id value as part of the key, i.e.{ fixedCacheKey: "keep-" + id }. Example sandbox fork:codesandbox.io/p/devbox/….
thank you for following up, I ended up usinguseQueryState like I shared on that example
@renatodamas Ah, ok, thanks. Cheers and good luck!
|

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.