How does React Query trigger a render?
Hello, I'm trying to track down a possible bug with dependent queries in React Query v4, and timers in Jest. I've encountered a similar issue with Cypress before (https://github.com/TanStack/query/issues/4655). I think the problem is related to React Query's use of timers but I'm still trying to debug.
My question is: where in the React Query code does it update its state so that observing components re-render? In useBaseQuery.ts I can see that it calls useState initially to create an Observer (https://github.com/TanStack/query/blob/96cdb28d311772774323c05a75372ed05eedfde8/packages/react-query/src/useBaseQuery.ts#L62) but I don't understand how or where that observer is updated so that it triggers a render when data is returned from the fetch function. I was expecting some sort of call to setState somewhere but I'm not able to find it.
In my test I can see that the dependent fetch function fires, and data is returned, but it doesn't look like React Query is then updating the observers.
Here's an annotated snippet of my test:
```tsx
describe('Account Management Bills Detail Page', () => {
beforeEach(async () => {
renderApp({
initialEntries: [
getResolvedPath(PATHS.ACCOUNT_MANAGEMENT_BILL_DETAIL, [74, 1]),
],
})
// We don't use Jest's fake timers anywhere in our test suite // But if I don't add these two lines then the dependent query never // updates and never triggers a render. jest.useFakeTimers() jest.runAllTimers() // Verify the initial page has loaded // This line will always fail if we don't do the fakeTimers trick expect( await screen.findByRole('heading', { name: 'Bill Details' }) ).toBeInTheDocument() })
// We don't use Jest's fake timers anywhere in our test suite // But if I don't add these two lines then the dependent query never // updates and never triggers a render. jest.useFakeTimers() jest.runAllTimers() // Verify the initial page has loaded // This line will always fail if we don't do the fakeTimers trick expect( await screen.findByRole('heading', { name: 'Bill Details' }) ).toBeInTheDocument() })
GitHub
Issues · TanStack/query
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - Issues · TanStack/query
GitHub
query/packages/react-query/src/useBaseQuery.ts at 96cdb28d311772774...
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - TanStack/query
3 Replies
environmental-rose•2y ago
but I don't understand how or where that observer is updated so that it triggers a render when data is returned from the fetch function.that's what useSyncExternalStore does: https://github.com/TanStack/query/blob/96cdb28d311772774323c05a75372ed05eedfde8/packages/react-query/src/useBaseQuery.ts#L77
GitHub
query/packages/react-query/src/useBaseQuery.ts at 96cdb28d311772774...
🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query. - TanStack/query
environmental-rose•2y ago
it should just work without fake timers
correct-apricotOP•2y ago
ah thank you @TkDodo 🔮 , I thought useSyncExternalStore was a React Query hook. I didn't realize it was part of React