3

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');
    },
  });
5
  • Is there anything preventing you from using a useQuery? Commented Jun 1, 2022 at 19:53
  • I edited the question and described why I couldn't use useQuery @JakubKotrs Commented Jun 2, 2022 at 8:21
  • well, if you never want the query to fire another request, you can set the cache and stale times to infinity. Is there any other reason to not use a query? If not, I will make an answer out of that. Commented Jun 2, 2022 at 17:57
  • I added { cacheTime: Infinity, staleTime: Infinity } to useQuery. when i liked a prototype, i changed the cache with optimistic update, after that, the new query has been fired!! I want to prevent useQuery to fire a new query after I like a prototype @JakubKotrs Commented Jun 3, 2022 at 11:00
  • Sound like you also need to stop invalidating the query manually. Commented Jun 3, 2022 at 22:13

1 Answer 1

4

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
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.