-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setNormalizedData should keep old updatedAt for queries that are affected #36
Comments
On further investigation, that change is not enough to support my use case. A call to A solution could be like this (tested and works for my use case): // normy-react-query/src/create-query-normalizer
const updateQueriesFromMutationData = (
mutationData: Data,
normalizer: ReturnType<typeof createNormalizer>,
queryClient: QueryClient,
) => {
const queriesToUpdate = normalizer.getQueriesToUpdate(mutationData);
queriesToUpdate.forEach(query => {
let queryKey = JSON.parse(query.queryKey) as QueryKey;
let cachedQuery = queryClient.getQueryCache().find({ queryKey });
// Remember the state of the isInvalidated boolean.
let isInvalidated = cachedQuery?.state.isInvalidated;
// Update the query based on mutation data or data from setNormalizedData().
queryClient.setQueryData(queryKey, () => query.data, {
updatedAt: cachedQuery?.state.dataUpdatedAt,
});
// Reset isInvalidated to its previous state.
if (isInvalidated) {
cachedQuery?.setState({ isInvalidated });
}
});
}; It gets a bit involved though. Another option entirely could be to allow the user to construct its own normalizer via That way I would get a lot more control and could implement my own |
I guess you mean this issue #19 ? I would love to add it to the core, but it needs being careful, as I am afraid to cause some infinite loops when you manually update data yourself. Regarding this issue, it actually makes sense, if you set some So I think your solution seems perfect, I would actually add it to the library and I do not think to even add any flag to conditionally turn it off/on. Do you see some danger? The worst what could happen is that when using |
Yes, #19 is what i meant. I'm currently using a syncing implementation like this: import { useQueryNormalizer } from '@normy/react-query'
import { useQueryClient } from '@tanstack/react-query'
import { useEffect } from 'react'
export function UpdateNormalizedQueriesOnRead({ children }) {
let queryNormalizer = useQueryNormalizer()
let queryClient = useQueryClient()
useEffect(() => {
// Update other queries when new data is received.
let unsubscribe = queryClient.getQueryCache().subscribe(event => {
if (
event.type === 'updated' &&
event.action.type === 'success' &&
event.action.data !== undefined &&
(event.query.meta?.normalize ?? true)
) {
const data = event.action.data
if (!event.action.manual) {
queryNormalizer.setNormalizedData(data)
}
}
})
return () => unsubscribe()
}, [])
return children
} and then wrapping my component tree in I believe the Regarding this issue, I think you are right that it should be safe to implement the One example when the changes maybe would feel a bit weird: await client.prefetchQuery({
queryKey: ['book'],
staleTime: 10_000,
queryFn: () =>
Promise.resolve({
id: '1',
name: 'Book 1',
author: 'Author 1',
}),
}); and then a mutation returns the data {
id: '1',
name: 'Book 1 updated',
author: 'Author 1',
} maybe one would expect the Also, maybe it's worth looking at if more query state should be preserved? This is the query state that's being set on {
...state,
data: action.data,
dataUpdateCount: state.dataUpdateCount + 1,
dataUpdatedAt: action.dataUpdatedAt ?? Date.now(),
error: null,
isInvalidated: false,
status: 'success',
...(!action.manual && {
fetchStatus: 'idle',
fetchFailureCount: 0,
fetchFailureReason: null,
}),
} in Should for example the previous network status and error (if there was any) be preserved? |
I think that generally Anyway, when you have |
You can actually have both So right now, if you have a query that's normalized, and then errors, a mutation that touches that query will reset the error even though the query itself never was retried with a successful response. So I think it makes sense to keep |
If that is the case, then you are right. I wonder though, why react-query does such things. As you say, it is usually wrong and unexpected to clear errors etc on manual updates like we do, so this should not be the default behiaviour. So what extra attrs we would like to preserve? |
I agree, it's weird that react-query resets those things. But at least in the case where the user manually calls I guess if we preserve That would mean we reset |
Yes, it is good that they provided an escape hatch :) Correct, If you could dedicate some time with the PR, I would be very grateful! I will wait for you with #31 BTW, as I would create conflicts, because I will move most of react-query package code to |
Thank you for the PR! Merged and released https://github.com/klis87/normy/releases/tag/%40normy%2Fcore%400.12.0 |
Great, thanks! |
With react-query, let's say there's a
books
query with a staleTime of 10s:After 10 seconds have passed, the query is considered
stale
. Let's say it's no longer on screen, so it should be refetched at the next mount.A call to
setNormalizedData
due to a mutation, or manually like this:will update the
dataUpdatedAt
property of every query that it touches.Book 1
in thebooks
query will be updated and thebooks
query will not be consideredstale
anymore and will not refetch at mount.I think this behaviour is wrong, as even though we got some partial data back for
Book 1
, the rest of the data and the other books were not refreshed, so thebooks
query should still be consideredstale
.One use case I have is where I (as someone discussed in another issue) automatically call
setNormalizedData
when queries receive new data (like Apollo which I have used before does). But when I callqueryClient.invalidateQueries()
on a mutation (I still sometimes do even with Normy), all queries will first invalidate, but thensetNormalizedData
causes queries to immediately become valid again, if a previous query updates their data in some way.Cause/fix
In the Normy internal function
updateQueriesFromMutationData
, react-query is called like this, which causesdataUpdatedAt
to update:The latest
dataUpdatedAt
timestamp can instead be preserved like this:Relevant discussion: TanStack/query#4716 (comment)
I made this as an issue instead of a PR since it could be seen as a breaking change (even though the current behaviour is not documented), so I wanted to get some input on this first. Another option could be to add a parameter to
setNormalizedData
where the user can decide if thedataUpdatedAt
timestamp should be touched or not.The text was updated successfully, but these errors were encountered: