Description
Describe the bug
Structural sharing causes issues where when I use setQueryData
to pass in completely new data, my useQuery
hooks does not rerender. It does return updated data, just doesn't re-render and useEffects
don't catch the data updates. Once I turn off structural sharing, everything works fine.
I have a hook that returns a map:
export function usePacks() {
const { data } = useQuery<Record<string, Pack>>(
['packs'],
fetchPacks,
{
staleTime: 1000 * 60,
cacheTime: Infinity,
});
return data;
}
Then I have a function that mutates this data, deep cloning to ensure no referential equality:
function updateCache (queryClient: QueryClient, newPack: Pack) {
const data = queryClient.getQueryData(['packs']);
data[newPack.id] = newPack;
queryClient.setQueryData(['packs'], JSON.parse(JSON.stringify(data)));
}
This is where it gets weird. usePacks
does not react at all to this data in terms of a re-render. usePacks
I believe will return the updated data, but it won't re-render, and useEffects
won't trigger:
function Component () {
const packs = usePacks();
useEffect(function () {
console.log('Does not trigger when it should');
}, [packs]);
useEffect(function () {
updateCache(queryClient, { id: 'bar' });
}, []);
return (
<!-- This actually renders the newest data. -->
<View>
{Object.values(packs).map(p => <Text>{p.id}</Text>)}
</View>
)
}
Sure it renders the data here as a result of other things triggering a re-render. But on other screens where I am using the hook (e.g., on other screens down the react-navigation
stack), it doesn't re-render and shows old data.
It Works if I Turn Off structuralSharing
The instant I turn off structural sharing, re-renders trigger as expected.
Your minimal, reproducible example
I added a Code Sandbox but I was unable to reproduce the issue in that environment. The code does show how it's set up in my codebase. I'm hoping this triggers some ideas from you
https://codesandbox.io/p/devbox/adoring-kepler-z93j2c
Steps to reproduce
- Have a useQuery that returns an object
- Use
setQueryData
to add a key to that object
Expected behavior
All components consuming that useQuery should re-render.
All useEffects
ingesting the data should fire.
How often does this bug happen?
None
Screenshots or Videos
No response
Platform
- React Native
- Expo
- React Query v4
Tanstack Query adapter
None
TanStack Query version
v4.36.1
TypeScript version
No response