useSWR 与后端分页集成

useSWR integration with pagination on backend

当页面更改时,将创建新查询并将其数据设置为 initialData。 在这种情况下,用户会在获取新查询数据之前看到 initialData:

import React from "react";

import fetch from "../lib/fetch";
import useSWR from "swr";

function Component({ initialData }) {
  const [page, setPage] = React.useState(1);
  const { data } = useSWR(
    `/api/data?page=${page}`,
    { initialData }
  );
  // ...
}
Component.getServerSideProps = async () => {
  const data = await fetch('/api/data?page=1');
  return { initialData: data };
};

我的问题是每次查询新数据时都将 initialData 用作后备:

关于如何防止这种闪烁,您有什么想法吗?

所以在react-query中,我认为有多种方法可以避免这种情况:

  1. keepPreviousData: true

这是实现分页的主要方式,也体现在docs as well as the examples.

它将确保当查询键发生变化时,在进行新的提取时,前一个查询键的数据会保留在屏幕上。结果对象将有一个 isPreviousData 标志设置为 true,这样你就可以,例如在转换发生时禁用下一个按钮或在它旁边显示一个小的加载微调器。它在 ux 中类似反应悬念将给我们(某个时候)。

  1. 初始数据函数

initialData 也接受函数,如果您不希望出现初始数据,则可以 return undefined。您可以将其与您的页面联系起来作为第一页,例如:

function Component({ initialData }) {
  const [page, setPage] = React.useState(1);
  const { data } = useQuery(
    ['page', id],
    () => fetchPage(id),
    { initialData: () => page === 1 ? initialData : undefined }
  );
}

请记住,在转换时您将有一个 loading 微调器,所以我认为这比方法 1 更糟糕。

  1. 由于您的 initialData 来自服务器,您可以尝试对整个 queryClient 进行水合。参见 the docs on SSR

initialDatakeepPreviousData 一起工作得很好,所以这里是文档中使用 initialData 的示例的 codesandbox 分支(解决方案 1)。我认为这是最好的选择:https://codesandbox.io/s/happy-murdock-tz22o?file=/pages/index.js