React如何避免不必要的重复渲染

React 组件在以下情况会重新渲染:

  1. 组件自身的状态 state 发生变化
  2. 父组件重新渲染(默认会连带所有子组件重新渲染)
  3. 组件接收的 props 发生变化

解决方法:

一、 React.memo (适用于函数组件)

工作原理

  • 对组件进行浅比较(shallow compare)props
  • 只有当 props 发生变化时才重新渲染

实现方式

const ChildComponent = React.memo(function ChildComponent(props) {
  // 组件内容
});

// 或者
const ChildComponent = React.memo((props) => {
  // 组件内容
});

工作流程

  1. 父组件渲染 → 准备传递给子组件的 props
  2. React 比较新旧 props(浅比较)
  3. 如果 props 未变化 → 跳过子组件渲染
  4. 如果 props 变化 → 重新渲染子组件

适用场景

  • 纯展示型组件
  • props 不经常变化的组件
  • 渲染开销较大的组件

二、 useMemo (缓存计算结果)

工作原理

  • 缓存计算结果
  • 只有当依赖项变化时才重新计算

实现方式

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

工作流程

  1. 组件渲染时检查依赖项
  2. 如果依赖项未变化 → 使用缓存值
  3. 如果依赖项变化 → 重新计算并缓存新值

三、 useCallback (缓存函数)

工作原理

  • 缓存函数引用
  • 避免因函数引用变化导致的不必要渲染

实现方式

const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

工作流程

  1. 组件渲染时检查依赖项
  2. 如果依赖项未变化 → 返回缓存的函数引用
  3. 如果依赖项变化 → 创建新函数并缓存

四、shouldComponentUpdate (类组件)

工作原理

  • 通过返回 true/false 控制是否更新

实现方式

class ChildComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    // 自定义比较逻辑
    return nextProps.value !== this.props.value;
  }
  
  render() {
    // 渲染内容
  }
}

五、 正确的 props(组件间数据传递机制) 设计

优化原则

  • 避免传递不必要的 props
  • 将 props 拆分为更小的独立部分
  • 避免传递大型对象作为 props

什么是props

一、Props的核心特性​​

​​单向数据流​​:只能从父组件传递到子组件
​​不可变性​​:子组件不能直接修改接收的props
​​动态渲染​​:组件根据传入的props呈现不同内容
​​类型安全​​:可通过PropTypes或TypeScript校验类型
​​二、基本语法与用法​​
​​1. 函数组件中使用Props​​

// 方式1:直接接收props对象
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
// 方式2:解构赋值(推荐)
function Welcome({ name }) {
  return <h1>Hello, {name}</h1>;
}
​​2. 类组件中使用Props​​
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
// 使用方式相同
<Welcome name="Bob" />

​​三、高级用法​​
​​1. 默认Props​​

// 函数组件(ES6默认参数)
function Greeting({ name = 'Guest' }) {
  return <p>Welcome, {name}!</p>;
}

// 类组件
Greeting.defaultProps = {
  name: 'Guest'
};

​​2. 传递复杂数据​​

// 传递对象
<UserProfile user={{ name: 'John', age: 30 }} />

// 传递数组
<ItemList items={['Apple', 'Banana']} />

// 传递函数(事件回调)
<Button onClick={() => alert('Clicked!')} />

​​3. Children Props​​

function Card({ children }) {
  return <div className="card">{children}</div>;
}

// 使用
<Card>
  <h3>Title</h3>
  <p>Content</p>
</Card>

​​四、类型检查(PropTypes)​​

import PropTypes from 'prop-types';

function User({ name, age }) {
  return <div>{name}, {age}</div>;
}

User.propTypes = {
  name: PropTypes.string.isRequired, // 必填字符串
  age: PropTypes.number,             // 可选数字
  hobbies: PropTypes.arrayOf(PropTypes.string) // 字符串数组
};
### React Native 组件优化策略 #### 一、理解渲染机制的重要性 为了有效避免不必要重复渲染,深入理解React渲染机制至关重要。当状态或属性发生变化时,React会重新渲染受影响的组件及其子组件。如果这些变化频繁发生而未加控制,则可能导致性能瓶颈[^1]。 #### 二、采用函数式组件与Hooks替代类组件 现代版本的React推荐使用函数式组件配合Hooks来代替传统的类组件形式。这种方式不仅简化了代码结构,而且通过`useMemo()` 和 `useCallback()` Hooks可以更精细地管理依赖关系,从而减少因父级传递下来的props改变所引起的子组件无意义更新。 ```javascript import React, { useMemo } from 'react'; function MyComponent({ data }) { const processedData = useMemo(() => processData(data), [data]); return ( // JSX here... ); } ``` #### 三、合理运用PureComponent/React.memo高阶组件 对于那些仅基于prop的变化决定是否应该再次渲染的情况,可以选择继承自`React.PureComponent`或者包裹一层`React.memo`。这两种方式都会自动执行浅比较操作,在前后两次接收相同参数时不触发新的渲染流程。 ```javascript // 使用 PureComponent 来防止不必要渲染 class Child extends React.PureComponent { render() { console.log('Child rendered'); return <div>{this.props.value}</div>; } } // 或者使用 memo 函数组件 const MemoizedChild = React.memo(function Child(props) { console.log('Child rendered'); return <div>{props.value}</div>; }); ``` #### 四、利用shouldComponentUpdate生命周期方法(针对Class Component) 在某些情况下可能需要更加复杂的逻辑判断当前实例是否有必要进行重绘工作。此时可以在Class Component内部覆写`shouldComponentUpdate(nextProps,nextState)` 方法来自定义条件。 ```javascript shouldComponentUpdate(nextProps, nextState){ if (nextProps.someProp !== this.props.someProp || nextState.someState !== this.state.someState ) { return true; } return false; } ``` #### 五、考虑虚拟化列表和其他UI模式 当处理大量数据项展示时,比如长列表滚动场景下,应优先选用支持按需加载更多项目的第三方库如`react-window`或内置FlatList组件中的windowSize prop设置以实现部分可见区域内的高效渲染效果[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值