是否可以在使用 React Query 更新缓存后重新渲染组件?

Is it possible to re-render a component after updating cache with React Query?

在根组件中,我从缓存中收到了这个数据。

  const queryClient = useQueryClient();
  const data = queryClient.getQueryData('prototypes');

在另一个组件中,在触发一个函数后,我更改了缓存中的数据(使用乐观更新)。 尽管缓存中的数据已更改并显示在 Devtools 中,但根组件中的新数据未显示且组件未刷新。

如何在更改缓存后重新渲染组件?

之前我在Nextjs中使用这种方式以Ssr方式获取数据

export const getServerSideProps = wrapper.getServerSideProps(
  (store) =>
    async ({ req }) => {
      const queryClient = new QueryClient();
      await queryClient.prefetchQuery('prototypes', getPrototypes);

      return {
        props: { dehydratedState: dehydrate(queryClient) },
      };
    }
);

在一个子组件中,我使用 useQuery hook 来获取数据。

  const { data: prototypes }: { data: FilterPrototypesByDateQuery } = useQuery(
    'prototypes',
    getPrototypes
  );

虽然数据存在于缓存中,但在安装此组件时,我在网络中看到触发了获取原型的新请求。

在其他子组件中,当我喜欢一个原型时,我使用乐观更新来更新缓存。但是我看到一个新的原型请求又被触发了。

 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');
    },
  });

如果您希望查询不再获取新数据,第一步是将其缓存和过时时间设置为无穷大。这使得 RQ 永远记住数据,但也总是 return 来自缓存。

const { data: prototypes } = useQuery('prototypes', getPrototypes, {
  cacheTime: Infinity,
  staleTime: Infinity,
});

下一步是您不应该手动使查询无效。当您使用 setQueryData 更改它时,它将被更新。

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
});