react-query手把手教程19-渲染优化

521 阅读3分钟

场景

当应用的复杂度很低时,你会发现应用会运行良好。但是一旦随着项目的迭代,功能代码随着需求的增加越来越复杂。这时你注意到其中有一个页面的渲染会有一些卡顿,此时使用react-query的devtools工具发现,某一个查询的渲染频率比你想象中的要高许多,并且它有很多的子组件,在这些组件中有一些消耗性能的操作,最终导致整体的页面变得很慢。

虽然可以想办法让组件渲染的更快,但是理论上来说你需要更多关注的是减少渲染次数的问题。react-query提供了一些特性来让开发者限制相关组件的渲染次数。

实践

降低渲染次数

react-query有许多的状态需要追踪,比如isLoadingisFetchingisError等。一般的使用场景下,从理论上来说react-query在获取数据时总是会渲染两次,一次是请求数据时isFetching设置为true,另一次是数据加载完成后isFetching设置为false

接下来让我们看一个例子,该示例每秒钟会从后端获取一个uuid字符串,并显示。

由于不支持内置codesandbox,请同学自行移步观看。👉🏻点击查看演示,如果无法访问,凑合看下下面的gif图

aa3a4473-0b20-4f7d-8094-72e0c1f51713.gif 你可以看到,由于在实际的代码中没有使用到isFetching状态,因此每次提取完数据后,只会发生一次渲染。并不是最开始我们说的两次渲染。


如果我们使用的数据没有改变,但是渲染次数仍然在增加。对于没有子组件的组件来说,没有太大的性能忧虑。但是对于拥有许多子组件的大型组件来说将会是一种灾难,将会由于数据的变化,引起许多不必要的重新渲染(虽然可能数据没变)。

为了帮助大家解决这个问题,react-query中提供了select配置项,它允许传入一个函数,该函数将会接收返回的数据,并在组件使用该数据前对其进行转换。react-query将会做深度等价检查,看我们从select函数返回的数据与之前是否匹配,如果匹配那么react-query就不会重新渲染该组件。

在下面的示例中,使用select选择返回的id属性。并且你也需要改变从data直接获取id的方式,因为select已经将对象转换成了字符串,👉🏻点击查看演示

const DisplayId = () => {
  const idQuery = useQuery(["id"], fetchId, {
    refetchInterval: 1000,
    select: (data) => data.id
  });


  return (
    <div>ID: {idQuery.data}</div>
  );
};

96935640-01db-49bc-a45c-89bd78ec5d1f.gif 你可以看到在这个例子中,不管如何刷新查询函数,由于数据没有发生改变,都不会触发重新渲染的操作。但是一旦id发生变化,那么就会重新执行渲染组件。目前渲染的两次分别是:第一次加载数据、数据返回后呈现这两次。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 27 天,点击查看活动详情