当一项更改时,React 会重新渲染整个列表
Posted
技术标签:
【中文标题】当一项更改时,React 会重新渲染整个列表【英文标题】:React re-renders entire list when one item is changed 【发布时间】:2018-04-10 12:02:00 【问题描述】:我有一个简单的 React 应用程序,它可以呈现 5000 种产品的名称和价格。价格是可编辑的,更改后价格会反映在状态中。
https://github.com/TonyCaffer/thinking-in-react-1
App.js 通过 onChangePrice 函数管理状态并处理价格变化,该函数被传递给 ProductTable 和每个 ProductRow
我使用 immutability-helpers 并且我专门只更改了已更改产品的状态记录。
但每次更改都会有明显的一秒延迟,因为 React 正在重新渲染所有产品。每个产品都有一个关键属性,我认为这有助于 React 只重新渲染必要的组件。
在生产版本中,它的滞后性较小,但所有产品都会重新渲染,这是我要解决的根本问题。
为什么要重新渲染所有产品组件?是因为我通过高级 ProductTable 传递 this.state.products 从而触发列表的总重绘?如果是这样,当状态在列表中时,每个 ProductRow 如何管理自己的记录状态?
【问题讨论】:
它不会停止重新渲染。他们的“关键”事物将调用之前调用的相同组件,并调用componentWillUpdate
而不是componentWillMount
。要停止渲染,请使用shouldComponentUpdate
停止重新渲染。
【参考方案1】:
React 将更新安排在两个阶段:协调器阶段(或渲染阶段,因为它涉及我们定义的组件的渲染方法)和提交阶段。当状态更新时,React 无论如何都会启动更新过程。使用适当的 shouldComponentUpdate 可以帮助您减少子组件中的更新次数
可能的解决方案:为ProductRow
使用shouldComponentUpdate
,如下所示:
shouldComponentUpdate(nextProps)
if (
this.props.guid !== nextProps.guid
|| // similarly check if the other new props are different
)
return true;
return false
上述检查将确保当父级检测到 setState 并在新的 React Fiber 的工作循环中安排更新时,不会重新计算子组件并且提交阶段完全跳过任何 DOM 更新。
Lin Clark explains the two phases 真的很好。它肯定会帮助您了解 React Fiber 如何管理更新。
您可以查看 React Virtualised 以提高对极长列表的感知性能。
【讨论】:
我添加了一个componentShouldUpdate函数。现在开发中的更新滞后,但生产没有滞后。我会认为这是一个很好的结果,并确保将我的应用程序架构成永远不会有这么大的列表。在我承诺之前,我想突破 React 的极限。 查看更新后的github:github.com/TonyCaffer/thinking-in-react-1以上是关于当一项更改时,React 会重新渲染整个列表的主要内容,如果未能解决你的问题,请参考以下文章
React Native:为啥 FlatList 会在数据更改时完全重新渲染?