当前位置: 首页 > article >正文

React PureComponent使用场景

1. 基本概念

1.1 什么是 PureComponent

PureComponent 是 React 提供的一个优化类组件,它通过自动实现 shouldComponentUpdate 生命周期方法,对 props 和 state 进行浅比较来决定是否需要重新渲染组件。

1.2 与 Component 的区别

// 普通 Component
class RegularComponent extends React.Component {
  render() {
    console.log('Regular Component render');
    return <div>{this.props.value}</div>;
  }
}

// PureComponent
class OptimizedComponent extends React.PureComponent {
  render() {
    console.log('Pure Component render');
    return <div>{this.props.value}</div>;
  }
}

2. 使用场景

React.PureComponent 是 React 中一个非常有用的类,它是 React.Component 的一个变种,主要用于优化性能。PureComponent 会自动实现 shouldComponentUpdate 方法,并基于 浅比较(shallow comparison) 来决定组件是否需要重新渲染。

PureComponent 的使用场景
组件的 props 和 state 变化不复杂且不深层嵌套

如果组件的 props 或 state 是简单类型(如 string、number、boolean 等),或者是浅层嵌套的对象数组,PureComponent 的性能优化非常有效。
PureComponent 会对 props 和 state 进行浅比较,如果值没有变化,组件就不会重新渲染。
使用场景:

比如当你有一个只渲染传入文本的组件,如果文本没有变化,PureComponent 会避免不必要的重新渲染。

class MyComponent extends React.PureComponent {
  render() {
    return <div>{this.props.text}</div>;
  }
}

组件渲染的内容相对静态,且频繁更新的场合

当某个组件被频繁地父组件更新(比如父组件经常调用 setState),但该组件的部分 props 或 state 没有变化时,使用 PureComponent 可以有效避免不必要的渲染,从而提升性能。
使用场景:

比如你有一个列表组件,父组件可能会触发更新,但列表项本身不会改变,使用 PureComponent 可以减少渲染的次数。

class ListItem extends React.PureComponent {
  render() {
    return <li>{this.props.name}</li>;
  }
}

需要避免深度比较的情况下

PureComponent 使用 浅比较 来判断 props 和 state 是否变化。如果你的 props 和 state 中包含的是对象或数组,并且这些对象是由父组件传递过来的新引用(即使它们的内容没变),PureComponent 也会认为它们发生了变化,导致重新渲染。
使用 PureComponent 可以避免显式编写 shouldComponentUpdate 来实现自定义的浅比较,特别是在简单应用中可以减少代码量。
避免在 shouldComponentUpdate 中手动比较

PureComponent 会自动处理浅比较,而你不需要手动编写 shouldComponentUpdate。这在很多情况下可以减少代码复杂度,避免开发者手动处理复杂的比较逻辑。
大白话:子组件不依赖当前状态变化时子组件使用PureComponent,父组件改变的值不要引起render渲染的时候,避免引用地址不变的对象属性值修改

2.1 简单数据类型的 props

// 适合使用 PureComponent 的场景
class NumberDisplay extends React.PureComponent {
  render() {
    return <div>{this.props.number}</div>;
  }
}

// 父组件
class Parent extends React.Component {
  state = { number: 1 };

  updateNumber = () => {
    this.setState({ number: 2 });
  };

  render() {
    return (
      <div>
        <NumberDisplay number={this.state.number} />
        <button onClick={this.updateNumber}>Update</button>
      </div>
    );
  }
}

2.2 复杂数据结构的处理

// 不恰当的使用方式
class BadExample extends React.PureComponent {
  render() {
    // 每次渲染都创建新对象,导致浅比较失效
    const data = { value: this.props.value };
    return <div>{data.value}</div>;
  }
}

// 正确的使用方式
class GoodExample extends React.PureComponent {
  render() {
    return <div>{this.props.data.value}</div>;
  }
}

// 父组件
class Parent extends React.Component {
  state = {
    data: { value: 'hello' }
  };

  updateValue = () => {
    // 创建新的对象引用
    this.setState({
      data: { ...this.state.data, value: 'world' }
    });
  };
}

3. 性能优化实践

3.1 避免内联对象

// 错误示例
class Parent extends React.Component {
  render() {
    return (
      <PureChild
        style={{ color: 'red' }}  // 每次渲染都创建新对象
        data={{ value: 42 }}      // 每次渲染都创建新对象
      />
    );
  }
}

// 正确示例
class Parent extends React.Component {
  style = { color: 'red' };  // 类属性,保持引用不变
  data = { value: 42 };      // 类属性,保持引用不变

  render() {
    return (
      <PureChild
        style={this.style}
        data={this.data}
      />
    );
  }
}

3.2 避免内联函数

// 错误示例
class Parent extends React.Component {
  render() {
    return (
      <PureChild
        onClick={() => console.log('clicked')}  // 每次渲染都创建新函数
      />
    );
  }
}

// 正确示例
class Parent extends React.Component {
  handleClick = () => {
    console.log('clicked');
  };

  render() {
    return (
      <PureChild
        onClick={this.handleClick}  // 使用类方法,保持引用不变
      />
    );
  }
}

3.3 使用不可变数据

class TodoList extends React.PureComponent {
  state = {
    todos: []
  };

  // 正确的更新方式
  addTodo = (todo) => {
    this.setState(prevState => ({
      todos: [...prevState.todos, todo]  // 创建新数组
    }));
  };

  updateTodo = (index, newTodo) => {
    this.setState(prevState => ({
      todos: prevState.todos.map((todo, i) =>
        i === index ? { ...todo, ...newTodo } : todo
      )
    }));
  };

  // 错误的更新方式
  wrongUpdate = (index, newTodo) => {
    const { todos } = this.state;
    todos[index] = newTodo;  // 直接修改数组
    this.setState({ todos });  // PureComponent 无法检测到变化
  };
}

4. 常见陷阱和解决方案

4.1 嵌套对象的比较

class NestedDataComponent extends React.PureComponent {
  state = {
    user: {
      profile: {
        name: 'John',
        age: 25
      }
    }
  };

  // 错误的更新方式
  wrongUpdate = () => {
    const { user } = this.state;
    user.profile.age = 26;  // 直接修改嵌套对象
    this.setState({ user });
  };

  // 正确的更新方式
  correctUpdate = () => {
    this.setState(prevState => ({
      user: {
        ...prevState.user,
        profile: {
          ...prevState.user.profile,
          age: 26
        }
      }
    }));
  };
}

4.2 数组更新

class ArrayComponent extends React.PureComponent {
  state = {
    items: [1, 2, 3]
  };

  // 错误的数组操作
  wrongArrayUpdate = () => {
    const { items } = this.state;
    items.push(4);  // 直接修改数组
    this.setState({ items });
  };

  // 正确的数组操作
  correctArrayUpdate = () => {
    this.setState(prevState => ({
      items: [...prevState.items, 4]
    }));
  };

  // 正确的过滤操作
  filterItems = (predicate) => {
    this.setState(prevState => ({
      items: prevState.items.filter(predicate)
    }));
  };
}

5. 最佳实践

5.1 何时使用 PureComponent

  1. 组件的 props 和 state 是简单数据类型
  2. 组件的渲染输出完全由 props 和 state 决定
  3. 组件需要频繁重渲染
  4. 组件的 props 和 state 变化频率较低

5.2 何时避免使用 PureComponent

  1. 组件的 props 经常变化
  2. 组件的渲染逻辑复杂
  3. 组件需要处理深层数据结构
  4. 组件依赖于外部状态或上下文

5.3 性能优化建议

// 1. 使用 memoization
class OptimizedComponent extends React.PureComponent {
  memoizedValue = memoize(value => expensiveOperation(value));

  render() {
    const processedValue = this.memoizedValue(this.props.value);
    return <div>{processedValue}</div>;
  }
}

// 2. 合理拆分组件
class ParentComponent extends React.Component {
  render() {
    return (
      <div>
        <PureChild1 data={this.props.data1} />
        <PureChild2 data={this.props.data2} />
      </div>
    );
  }
}

6. 总结

6.1 核心要点

  1. PureComponent 通过浅比较优化性能
  2. 适用于简单数据结构的场景
  3. 需要注意引用类型的处理
  4. 配合不可变数据使用效果最佳

6.2 使用建议

  1. 合理评估使用场景
  2. 避免内联对象和函数
  3. 正确处理复杂数据结构
  4. 注意性能优化的边界条件

http://www.kler.cn/a/487518.html

相关文章:

  • Linux第一课:c语言 学习记录day06
  • Photon最新版本PUN 2.29 PREE,在无网的局域网下,无法连接自己搭建的本地服务器
  • 腾讯云AI代码助手编程挑战赛-图片转换工具
  • Google Play开发者账号的高风险行为解析
  • 什么是网络安全攻防演练,即红蓝对抗?
  • 数据结构:LinkedList与链表—面试题(三)
  • 基于SpringBoot的时间管理系统设计与实现
  • Spring Boot + MyBatis Plus 存储 JSON 或 List 列表全攻略
  • matlab离线安装硬件支持包
  • WPF连接USB相机,拍照,视频 示例
  • 《Spring Framework实战》4:Spring Framework 文档
  • Qt仿音乐播放器:媒体类
  • 降噪去噪学习流程和算法分类总结
  • 6 分布式限流框架
  • 蓝桥杯 第十五届 研究生组 B题 召唤数学精灵
  • C# 使用iText 编辑PDF
  • Golang学习笔记_23——error补充
  • AI绘画:Midjourney和stable diffusion到底有什么区别?
  • 基于单片机的空调温度测试测控系统设计
  • es 单个节点cpu过高
  • EasyExcel(二)导出Excel表自动换行和样式设置
  • 大数据高级ACP学习笔记(3)
  • 腾讯云AI代码助手编程挑战赛-武器大师
  • 109周四复盘 (183)慢速
  • Spring AMQP-lazy队列
  • spring boot controller放到那一层