Reputation: 374
In The root component, I received this data from the cache.
const queryClient = useQueryClient();
const data = queryClient.getQueryData('prototypes');
In another component, after firing a function, I changed the data on cache (with optimistic update). Although the data was changed in cache and shown in Devtools, new data in root component was not showing and component didn't refresh.
how can I re-render a component after changing cache?
Before, I used this way to get data in Ssr mode in Nextjs.
export const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({ req }) => {
const queryClient = new QueryClient();
await queryClient.prefetchQuery('prototypes', getPrototypes);
return {
props: { dehydratedState: dehydrate(queryClient) },
};
}
);
In a child component, I used useQuery hook to get data.
const { data: prototypes }: { data: FilterPrototypesByDateQuery } = useQuery(
'prototypes',
getPrototypes
);
Although data was existed in cache, when this component was mounted, in network I saw that a new request to get prototypes was fired.
In other child component, when i liked a prototype, i used optimistic update to update cache. But i saw that a new request for prototypes was fired again.
const { mutate: likePrototype } = useLikePrototypeMutation({
onMutate: async (like) => {
const previousPrototype: FilterPrototypesByDateQuery =
queryClient.getQueryData('prototypes');
const newState = produce(previousPrototype, (draft) => {
const index = draft.prototype_getPrototypes.result.items.findIndex(
(item) => item.id === prototypeId
);
if (index > -1) {
draft.prototype_getPrototypes.result.items[index].isLiked = true;
}
});
queryClient.setQueryData('prototypes', newState);
return { previousPrototype };
},
onSettled: () => {
queryClient.invalidateQueries('prototypes');
},
});
Upvotes: 3
Views: 5872
Reputation: 6244
The first step when you want a query to not fetch new data ever again, is to set its cache and stale times to infinity. This makes RQ remember the data forever but also always return from cache.
const { data: prototypes } = useQuery('prototypes', getPrototypes, {
cacheTime: Infinity,
staleTime: Infinity,
});
The next step is that you should not be manually invalidating the query. When you change it using setQueryData
, it will be updated.
const { mutate: likePrototype } = useLikePrototypeMutation({
onMutate: async (like) => {
// ...
// this causes the component using that query to update
queryClient.setQueryData('prototypes', newState);
// ...
},
// no onSettled here
// just rollback in onError
});
Upvotes: 4