From 857d68f703332bd76458f1a977143e2ee8c428cb Mon Sep 17 00:00:00 2001 From: Johan Bergman Date: Tue, 7 Jan 2025 19:30:40 +0100 Subject: [PATCH 1/2] Keep relevant query state in setNormalizedData --- .../src/create-query-normalizer.spec.ts | 52 +++++++++++++++++++ .../src/create-query-normalizer.ts | 23 ++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/packages/normy-react-query/src/create-query-normalizer.spec.ts b/packages/normy-react-query/src/create-query-normalizer.spec.ts index a3ba088..56d7515 100644 --- a/packages/normy-react-query/src/create-query-normalizer.spec.ts +++ b/packages/normy-react-query/src/create-query-normalizer.spec.ts @@ -521,4 +521,56 @@ describe('createQueryNormalizer', () => { }, }); }); + + it('keeps relevant query state on queries after setNormalizedData', async () => { + const client = new QueryClient(); + const normalizer = createQueryNormalizer(client); + normalizer.subscribe(); + + await client.prefetchQuery({ + queryKey: ['book'], + queryFn: () => + Promise.resolve({ + id: '1', + name: 'Name', + }), + }); + + // Set error state on the query. + await client.prefetchQuery({ + queryKey: ['book'], + queryFn: () => { + throw new Error('Failed to fetch'); + }, + }); + + // Set isInvalidated on the query. + client.invalidateQueries({ queryKey: ['book'] }); + + let state1 = client.getQueryCache().find({ queryKey: ['book'] })?.state; + + let dataUpdatedAt1 = state1?.dataUpdatedAt; + let isInvalidated1 = state1?.isInvalidated; + let error1 = state1?.error; + let status1 = state1?.status; + + await sleep(1); + + normalizer.setNormalizedData({ + id: '1', + name: 'Name updated', + }); + + let state2 = client.getQueryCache().find({ queryKey: ['book'] })?.state; + + let dataUpdatedAt2 = state2?.dataUpdatedAt; + let isInvalidated2 = state2?.isInvalidated; + let error2 = state2?.error; + let status2 = state2?.status; + + expect(dataUpdatedAt1).toEqual(dataUpdatedAt2); + expect(isInvalidated1).toEqual(isInvalidated2); + expect(error1).toEqual(error2); + expect(status1).toEqual(status2); + }); }); diff --git a/packages/normy-react-query/src/create-query-normalizer.ts b/packages/normy-react-query/src/create-query-normalizer.ts index 61b0d02..bdaf809 100644 --- a/packages/normy-react-query/src/create-query-normalizer.ts +++ b/packages/normy-react-query/src/create-query-normalizer.ts @@ -24,10 +24,25 @@ const updateQueriesFromMutationData = ( const queriesToUpdate = normalizer.getQueriesToUpdate(mutationData); queriesToUpdate.forEach(query => { - queryClient.setQueryData( - JSON.parse(query.queryKey) as QueryKey, - () => query.data, - ); + let queryKey = JSON.parse(query.queryKey) as QueryKey; + let cachedQuery = queryClient.getQueryCache().find({ queryKey }); + + // react-query resets some state when setQueryData() is called. + // We'll remember and reapply state that shouldn't + // be reset when a query is updated via Normy. + + // dataUpdatedAt and isInvalidated determine if a query is stale or not, + // and we only want data updates from the network to change it. + let dataUpdatedAt = cachedQuery?.state.dataUpdatedAt; + let isInvalidated = cachedQuery?.state.isInvalidated; + let error = cachedQuery?.state.error; + let status = cachedQuery?.state.status; + + queryClient.setQueryData(queryKey, () => query.data, { + updatedAt: dataUpdatedAt, + }); + + cachedQuery?.setState({ isInvalidated, error, status }); }); }; From 2d517fedd11f10a060de9ff3efd16252bed0420a Mon Sep 17 00:00:00 2001 From: Johan Bergman Date: Tue, 7 Jan 2025 19:39:14 +0100 Subject: [PATCH 2/2] Follow coding style --- .../src/create-query-normalizer.spec.ts | 22 +++++++++---------- .../src/create-query-normalizer.ts | 12 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/normy-react-query/src/create-query-normalizer.spec.ts b/packages/normy-react-query/src/create-query-normalizer.spec.ts index 56d7515..ef68333 100644 --- a/packages/normy-react-query/src/create-query-normalizer.spec.ts +++ b/packages/normy-react-query/src/create-query-normalizer.spec.ts @@ -545,14 +545,14 @@ describe('createQueryNormalizer', () => { }); // Set isInvalidated on the query. - client.invalidateQueries({ queryKey: ['book'] }); + await client.invalidateQueries({ queryKey: ['book'] }); - let state1 = client.getQueryCache().find({ queryKey: ['book'] })?.state; + const state1 = client.getQueryCache().find({ queryKey: ['book'] })?.state; - let dataUpdatedAt1 = state1?.dataUpdatedAt; - let isInvalidated1 = state1?.isInvalidated; - let error1 = state1?.error; - let status1 = state1?.status; + const dataUpdatedAt1 = state1?.dataUpdatedAt; + const isInvalidated1 = state1?.isInvalidated; + const error1 = state1?.error; + const status1 = state1?.status; await sleep(1); @@ -561,12 +561,12 @@ describe('createQueryNormalizer', () => { name: 'Name updated', }); - let state2 = client.getQueryCache().find({ queryKey: ['book'] })?.state; + const state2 = client.getQueryCache().find({ queryKey: ['book'] })?.state; - let dataUpdatedAt2 = state2?.dataUpdatedAt; - let isInvalidated2 = state2?.isInvalidated; - let error2 = state2?.error; - let status2 = state2?.status; + const dataUpdatedAt2 = state2?.dataUpdatedAt; + const isInvalidated2 = state2?.isInvalidated; + const error2 = state2?.error; + const status2 = state2?.status; expect(dataUpdatedAt1).toEqual(dataUpdatedAt2); expect(isInvalidated1).toEqual(isInvalidated2); diff --git a/packages/normy-react-query/src/create-query-normalizer.ts b/packages/normy-react-query/src/create-query-normalizer.ts index bdaf809..c459f6e 100644 --- a/packages/normy-react-query/src/create-query-normalizer.ts +++ b/packages/normy-react-query/src/create-query-normalizer.ts @@ -24,8 +24,8 @@ const updateQueriesFromMutationData = ( const queriesToUpdate = normalizer.getQueriesToUpdate(mutationData); queriesToUpdate.forEach(query => { - let queryKey = JSON.parse(query.queryKey) as QueryKey; - let cachedQuery = queryClient.getQueryCache().find({ queryKey }); + const queryKey = JSON.parse(query.queryKey) as QueryKey; + const cachedQuery = queryClient.getQueryCache().find({ queryKey }); // react-query resets some state when setQueryData() is called. // We'll remember and reapply state that shouldn't @@ -33,10 +33,10 @@ const updateQueriesFromMutationData = ( // dataUpdatedAt and isInvalidated determine if a query is stale or not, // and we only want data updates from the network to change it. - let dataUpdatedAt = cachedQuery?.state.dataUpdatedAt; - let isInvalidated = cachedQuery?.state.isInvalidated; - let error = cachedQuery?.state.error; - let status = cachedQuery?.state.status; + const dataUpdatedAt = cachedQuery?.state.dataUpdatedAt; + const isInvalidated = cachedQuery?.state.isInvalidated; + const error = cachedQuery?.state.error; + const status = cachedQuery?.state.status; queryClient.setQueryData(queryKey, () => query.data, { updatedAt: dataUpdatedAt,