0

I have a MediaCard component, the one containing an img element with an url with a token. This token must first be required in order to get the image. The caveat here is that the token will expire in 30 seconds. It would be something like this:

const MediaCard = () => {

    // This should refetch the token everytime a new component is 
    // mounted and 30 seconds has passed since the last fetch

    const { data: token, error: tokenError, isLoading: tokenIsLoading } = useGetTokenQuery(undefined, { refetchOnMountOrArgChange: 30 });

    if (tokenError) return 'Error'

    if (tokenIsLoading) return 'Loading skeleton'

    return (
       <img url={`/url/${token}/image1.jpg`}
    )
     

This was all working fine when I have only one MediaCard component. The problem started when I mounted the first media card, loaded the token and then render the image. Then, if I let 30 seconds pass, when I try to mount a new MediaCard, the hook will start refetching the token, but keeping the old data. That brought two different issues:

  1. When the new component mount, as we have an expired token as data, the image would fail to load. Then, after the new token was received, the image would re-render and then worked.
  2. Once the new token was received, all the previous mounted images would re-render. I would like that once the image is render with a valid token to keep that way and don't render again.

Maybe the solution is not regarding RTK Query but React itself.

Nicolas
  • 1,193
  • 1
  • 10
  • 25

1 Answers1

1

The point of RTK Query "queries" is to "reflect" the state of the server - which means that we assume that a request for a certain endpoint with the same arguments will always have the most "up-to-date" response (treating those as REST resources) - and will keep all those query responses synchronized with each other over component boundaries.

In your case, it seems you don't want that, you want these to be local to the component. To be honest, you don't need a global state like Redux for that - you could just make the request and save the response into local component state.

If you want to use RTK Query for it nonetheless, you should probably go for mutations instead of queries here - since mutation results are unique per component. And just trigger the mutation trigger in a useEffect directly after component mount.

phry
  • 35,762
  • 5
  • 67
  • 81
  • 1
    Yes, I know it's not the point of the library, but I am already using in the rest of the app and would rather make requests in the same way. The one think I wanted to leverage from the library was to cache the token for 30 seconds. I got it to work, but once the token was refreshed all other MediaCard components were also refreshed. So I am trying now to find a way to "fix" the components that already got a previous token not to re-render once a new token is received. Maybe using React.memo ? – Nicolas Jan 06 '22 at 15:39
  • As I already told you. Use a mutation, not a query. That way the result is indivdual per component. – phry Jan 06 '22 at 15:44
  • That will work, but I would not be able to cache the token up to 30 seconds, right? – Nicolas Jan 06 '22 at 15:53
  • It would hold it infinitely per component as long as it is mounted, but not share it between the components. – phry Jan 06 '22 at 16:49