1

NOTE: I'm not trying to call the query hook in another component which should return cached data if the same arguments were passed to the hook avoiding a new request to be made, my issue is when forcing a refetch.

I'm working on a React Native project and I'm having a small confusion regarding the inner workings of RTK Query when it comes to refetching fresh data and I can't seem to find an answer online.

I have a query that's getting triggered when the component mounts, and I have a useEffect that has the fetched data (which is an array of objects) in its dependencies array like so:

    function MyComponent(props){
      ...
    
      const {
        data: teams,
        refetch,
      } = useGetUserTeamsQuery({userId}, {skip: !userId || !rolesToken});

      useEffect(()=>{
        if(teams){
          console.log("teams changed...")
        } 
      }, [teams])

    }

Now when the component first mounts I get teams changed... in the logs as expected, then when some event fires (socket reconnects) I call refetch to refetch fresh data in case the list of teams changed when the socket was disconnected, and the behavior I'm getting is:

After the refetch, my useEffect doesn't execute when I have the exact same result being returned from the server, which is confusing to me since I can see in my debugger that the request actually fires and goes from pending status to fulfilled, so normally I should be having a new reference to the array teams thus my useEffect should get triggered since the reference has changed even if the data is still the same.

Then when update the list of teams (adding the user to a new team for example) my useEffect executes and I get the log in the console.

So my question is, does RTK Query perform some sort of comparison between the cached data and the newly fetched one to determine if the data has somehow changed and if the answer is no it would return the same reference ?

abdou-tech
  • 687
  • 1
  • 8
  • 16
  • 1
    What’s your cache key? – Dave Newton May 25 '23 at 11:27
  • @DaveNewton it's `"getUserTeams({"userId":"some_user_id"})"` – abdou-tech May 25 '23 at 11:33
  • 1
    Is the user ID changing between requests? – Dave Newton May 25 '23 at 11:35
  • @DaveNewton No it's the exact same `userId` since the arguments aren't changing, I'm just triggering the refetch manually with the same args – abdou-tech May 25 '23 at 11:36
  • 2
    That's what caching is: if the cache key matches it returns the cached data. Maybe I'm misreading your question. – Dave Newton May 25 '23 at 11:37
  • @DaveNewton But I can see in my debugger the the request is actually firing, it's `pending` for a while then it becomes `fulfilled`, so I'm assuming there's new data being fetched ? Also from my understanding calling `refetch` would normally force a refetch regardless of the cache key I'm I wrong ? – abdou-tech May 25 '23 at 11:42
  • Ah, I see what you mean--you're correct, the refetch function should refetch the data. I'm not sure--IIRC by default RTK uses Immer so maybe there's some comparison logic in there? Not sure. – Dave Newton May 25 '23 at 11:50
  • @DaveNewton Exactly that's my question, is there any comparison logic and if there is how does it work – abdou-tech May 25 '23 at 13:10
  • If there is it'd work like you'd expect; a deep compare. Immer may do this automagically--you'd likely need to look at both the rtk-query code and possibly the Immer code if it isn't explicit in the documentation. – Dave Newton May 25 '23 at 13:54
  • 1
    Does this answer your question? [Redux Tool Kit Query: Need same data in different two components but without duplicate requests](https://stackoverflow.com/questions/73348227/redux-tool-kit-query-need-same-data-in-different-two-components-but-without-dup) – Yilmaz May 25 '23 at 14:52
  • @Yilmaz Thanks for your comment but unfortunately it does not, in my case I'm not calling the query hook in a different component which should return the cached data if called with the same argument, but instead I'm forcing a refetch in the same component and somehow still getting the same result – abdou-tech May 25 '23 at 15:17
  • @DaveNewton Haven't had the time to look into the code yet but I highly doubt they implemented a deep comparison since the shape of the returned data is unknown and could be absolutely anything and it would be a huge performance hit for large lists that contain deeply nested objects – abdou-tech May 25 '23 at 15:20
  • @abdou-tech Must be magic then. – Dave Newton May 25 '23 at 15:21

1 Answers1

0

Yes, if a new query will return the same data as the last query, you will get the same object back, to prevent unexpected (and unneccessary) rerender.

Even if a query will return partially equal data, that part of data will be kept stable.

Your useEffect here is a data synchronization mechanism - so unless data doesn't change, it will not reexecute. If this causes a problem with your logic, you are likely abusing useEffect for something it should not be used for, and should probably rethink the actual logic that you are applying.

phry
  • 35,762
  • 5
  • 67
  • 81