react性能优化:提取子组件中额外的事件绑定

react性能优化:提取子组件中额外的事件绑定

我们经常在快要完成一个react中型应用时,发现页面并没有想象中那么流畅。 react 理论性能是不错的,但是对开发者要求也很高,一些不易注意的点很容易造成性能问题。正所谓“烂泥扶不上墙”。

下面看看子组件的事件绑定写法对性能的影响。

这是React中的常见情况:您正在映射数组,您需要每个项目调用点击处理程序和一些相关数据。

这是一个例子。我正在迭代一个用户列表,并将userId传递给第29行的deleteUser函数。

这是Codeandbox上的一个工作示例。(真棒)

所以, 有什么问题?

我在点击处理程序中使用箭头函数。这意味着每次渲染运行时,都会分配一个新函数。在许多情况下,这不是一件多大的事。但是,如果您有子组件,即使数据没有更改,它们也将重新渲染,因为每个渲染分配一个新的函数。

底线:避免在渲染中声明箭头函数或绑定以获得最佳性能。我的团队使用这个ESLint规则帮助提醒我们这个问题。

解决方案是什么?

那么你如何在渲染中避免绑定和箭头函数呢?一个选项是提取一个子组件。在这里,我将列表项提取到UserListItem.js

然后,父组件的渲染变得更简单,不再需要包含箭头函数。它只是通过props传递每个列表项的相关上下文:

这是一个重构的工作实例

Yay or Yuck?

此模式通过消除冗余的函数分配来提高性能。所以当这种情况适用于您的组件时,它是最有用的:

  • 渲染频繁被调用
  • 渲染子组件非常耗时

诚然,我提取子组件也是我提到的一个额外的工作。它需要更多的移动部件和更多的代码。所以如果你没有出现性能问题,可以说这是一个过早的优化。

所以你有两个选择:允许箭头和绑定到任何地方(如果有性能问题再处理),或禁止他们获得最佳性能和一致性。

底线:我建议禁止箭头函数并在render中绑定。下面就是为什么:

  • 你必须禁用我上面建议的有用的ESLint规则来允许它。
  • 禁用linting规则后,人们可能会复制此模式,并开始禁用其他linting规则。一个处例外可以很快成为规范…

所以我发现提取子组件是一个有用的模式,以避免在渲染中绑定。

其他的反例

还有些人会想要这样写:

deleteUser = id=() => {
 this.setState(prevState => {
 return { users: prevState.users.filter( user => user.id !== id)}
 })
}
// …
onClick={this.deleteUser(user.id)}

他们认为传递参数会比其他方式更加方便。但这和第一个糟糕的例子并无太大区别,子组件同样会再次渲染。

如果有相当多类似的输入框,像这样:

<form>
Render = () =>
Input1 value=this.state.input1 onChange= update state for field1
Input2….
Input3….

官方给出的方法是给每个 input 添加 name 属性,进而获取参数。

当然也有人会想要在 html 上动文章,比如添加自定义属性 data-id=${userId}。这当然也能实现,但是 html不应该是数据源,这应该避免。

【翻译原文】:(有改动)https://medium.freecodecamp.org/react-pattern-extract-child-components-to-avoid-binding-e3ad8310725e

0%