在参数更改时使用 useQuery 重新获取

Re-fetching with useQuery on argument change

我正在尝试使用 react-query 实现分页。在页面更改时,我正在使用 setArrivals 更新 useEffect 内的页面。出于某种原因,我总是发送 arrivals 的先前值作为 getProductList 函数的参数。为了解决这个问题,我在 setTimeout 中发送了 refetch() 请求。它确实有效,但我觉得不合适。让我知道我做错了什么。

const HomePage = ({ newArrivals }) => {
  const [page, setPage] = useState(1);
  const [arrivals, setArrivals] = useState({ ...newArrivals, page: page });

  useEffect(() => {
    setArrivals((values) => {
      console.log({ page });
      return { ...values, page: page };
    });
    setTimeout(function () {
      newArrivalsQuery.refetch();
    }, 0);
  }, [page]);

  const newArrivalsQuery = useQuery(
    ['productListByNewArrivals'],
    () => getProductList(arrivals),
    {
      select: useCallback((data) => {
        return JSON.parse(data);
      }, []),
    }
  );

  return (
    <>
      <NewArrivals
        newArrivalsQuery={newArrivalsQuery}
        page={page}
        setPage={setPage}
      />
    </>
  );
};

export async function getServerSideProps(context) {
  const newArrivals = {
    sort: 'createdAt',
    order: 'desc',
  };

  try {
    const queryClient = new QueryClient();

    await queryClient.prefetchQuery('productListByNewArrivals', async () => {
      const newArrivalsResult = await listProduct(newArrivals);
      return JSON.stringify(newArrivalsResult);
    });

    return {
      props: {
        newArrivals: newArrivals,
        dehydratedState: dehydrate(queryClient),
      },
    };
  } catch (error) {
    console.log('error: ', error);
    if (error) {
      return {
        redirect: {
          destination: '/login',
          permanent: false,
        },
      };
    }
  }
}

最好的方法是将查询函数的依赖项添加到 queryKey。 react-query 是声明式的,如果 queryKey 发生变化,它将自动重新获取。如果您必须达到 useEffectrefetch,这可能不是最简单的解决方案:

const HomePage = ({ newArrivals }) => {
  const [page, setPage] = useState(1);
  const [arrivals, setArrivals] = useState({ ...newArrivals, page: page });

  const newArrivalsQuery = useQuery(
    ['productListByNewArrivals', arrivals],
    () => getProductList(arrivals),
    {
      select: useCallback((data) => {
        return JSON.parse(data);
      }, []),
    }
  );

现在,arrivals 是 queryKey 的一部分,这就是您在 getProductList 的 queryFn 中使用的内容。现在您需要做的就是调用 setArrivals 并且 react-query 将重新获取。

旁注:看起来 arrivals 并不是真正的 state,而是 derived state。至少在这个片段中,你只调用了 setter 效果,这似乎是错误的。看起来你想与 page 保持同步并在每次调用 setPage 时计算它,所以你也可以这样做:

  const [page, setPage] = useState(1);
  const arrivals = { ...newArrivals, page: page };