You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React状态变更重渲染性能优化及key props作用解析

Hey 👋,这两个问题都是React性能优化里的核心点,我来给你捋清楚:

1. 当状态变化时,React如何提升重渲染性能?

React主要靠这几个核心机制和优化手段来减少不必要的重渲染:

  • 虚拟DOM + Diff算法:React不会直接操作真实DOM,而是先在内存里维护一份虚拟DOM(JS对象)。当状态变化时,它会对比新旧虚拟DOM的差异,只把变化的部分同步到真实DOM,避免了整棵DOM树的重新渲染,这是最基础的性能保障。
  • 组件重渲染控制:
    • 类组件可以用PureComponent(自动浅比较props和state)或者手动实现shouldComponentUpdate方法,判断组件是否需要更新;
    • 函数组件则可以用React.memo包裹,实现类似PureComponent的浅比较效果,阻止props没变化时的重渲染。
  • 缓存计算与函数引用:用useMemo缓存复杂计算的结果,避免每次重渲染都重复计算;用useCallback缓存函数引用,防止因为函数引用变化导致子组件不必要的重渲染。
  • 状态粒度拆分:尽量把状态拆分成更小的独立单元,只让依赖该状态的组件更新,而不是让整个父组件连带所有子组件都重渲染。
2. key属性提升重渲染性能的作用原理

先给你说清楚React渲染列表的逻辑:当你用map渲染列表时,React需要知道每个列表项的“身份”,这样在列表发生变化(增删改、排序)时,才能准确判断哪些项是新增的、哪些是删除的、哪些只是位置变了。

key的核心作用:

  • 唯一标识列表项:key是React用来识别每个列表元素的唯一标识,它必须是稳定、唯一的(不能随列表变化而改变)。
  • 优化Diff过程:没有key的时候,React会默认用元素在列表中的索引来做标识,但如果列表顺序变化(比如删除中间项、排序),索引会跟着改变,React会误以为后面的所有元素都变了,从而重新渲染这些元素,这就造成了不必要的性能浪费,甚至可能导致组件状态混乱。

举个例子:假设你有个列表[A,B,C],索引是0、1、2。如果你删除B,变成[A,C],索引变成0、1。没有key的话,React会认为原来的C(索引2)被删除了,然后把原来的A(索引0)保留,把原来的C改成现在的C(索引1)——这其实是没必要的,因为C本身没变化,只是位置变了。但如果用每个项的唯一id当key,React就能直接识别出B被删除了,A和C只是位置没变,不需要重新渲染它们。

关于你示例代码里的小问题:

你示例中用了key={i}(索引当key),这种方式只适合列表不会发生顺序变化、不会增删项的场景。如果你的列表有排序、添加删除操作,最好用数据本身的唯一标识,比如示例里的person.id,改成key={person.id}才是更稳妥的做法。

修正后的示例代码:

import React from 'react';
class App extends React.Component {
  constructor() {
    super();
    this.state = {
      data: [
        { "id":1, "name":"Foo", "age":"20" },
        { "id":2, "name":"Bar", "age":"30" },
        { "id":3, "name":"Baz", "age":"40" }
      ]
    }
  }
  render() {
    return (
      <div>
        <Header/>
        <table>
          <tbody>
            {this.state.data.map((person) => <TableRow key = {person.id} data = {person} />)}
          </tbody>
        </table>
      </div>
    );
  }
}
class Header extends React.Component {
  render() {
    return (
      <div>
        <h1>Header</h1>
      </div>
    );
  }
}
class TableRow extends React.Component {
  render() {
    return (
      <tr>
        <td>{this.props.data.id}</td>
        <td>{this.props.data.name}</td>
        <td>{this.props.data.age}</td>
      </tr>
    );
  }
}
export default App;

内容的提问来源于stack exchange,提问作者hatellla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:02:28