Render
在React中,组件的render方法可能因为以下原因被触发:
-
初始化渲染: 当组件首次被挂载(mounted)到DOM中时,
render方法会被调用。 -
状态变化 (setState): 当组件的状态通过
setState方法发生变化时,组件会重新渲染。但这并不总是会立即导致render方法被调用,因为React可能会批量处理多个setState操作以优化性能。 -
Props 变化: 当组件接收到新的props时,
render方法可能会被调用。不过,如果你使用shouldComponentUpdate或者PureComponent,并且props没有真正改变,那么渲染可能会被阻止。 -
Context 变化: 如果组件订阅了某个context,并且这个context的值发生了变化,那么组件可能会重新渲染。
-
强制更新 (forceUpdate): 使用
component.forceUpdate()方法可以强制组件重新渲染,即使状态和props都没有变化。但是这种方法并不是推荐的,因为它跳过了React的普通的更新和重渲染逻辑。 -
Parent Re-renders: 如果一个父组件重新渲染,其子组件也可能会重新渲染,除非子组件通过
shouldComponentUpdate或者是PureComponent进行了优化。 -
使用Hooks: 如果你使用React Hooks,特别是
useState或useContext,它们的变化也可能导致组件重新渲染。 -
Hot Module Replacement (HMR): 在开发环境中,使用如Webpack的热模块替换功能可以导致组件重新渲染。
注意:React有多种机制来避免不必要的渲染,例如shouldComponentUpdate方法、React.memo、和PureComponent。这些工具可以帮助避免因数据没有实际改变而导致的不必要渲染。
shouldComponentUpdate
shouldComponentUpdate 是 React 组件生命周期中的一个方法。它允许我们手动地判断组件在接下来的状态或属性变化时是否应该更新。这是一个性能优化手段,用于避免不必要的渲染。
使用:
当组件的状态或属性发生变化时,shouldComponentUpdate 会被自动调用。此方法接收两个参数,即将要更新的新属性 (nextProps) 和新状态 (nextState)。
shouldComponentUpdate(nextProps, nextState) {
// 返回 true 或 false
}
返回值:
- 如果此方法返回
true,则组件会继续更新流程,最终调用render方法。 - 如果此方法返回
false,则组件不会进入渲染流程,从而跳过渲染。
注意点:
-
不要产生副作用: 在
shouldComponentUpdate内部不应该调用this.setState或产生其他副作用。 -
默认行为: 如果不定义
shouldComponentUpdate,则默认行为是每次状态或属性变化都重新渲染。 -
与 PureComponent: React 提供了一个
PureComponent,它自动地为所有的属性和状态字段进行浅比较,如果都没有变化,则跳过渲染。使用PureComponent可以帮助我们避免手动编写shouldComponentUpdate。 -
与函数组件和 React.memo: 对于函数组件,没有生命周期方法可以使用,但你可以使用
React.memo来达到相似的效果。
示例:
class MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
// 仅当属性 name 发生变化时才重新渲染
return nextProps.name !== this.props.name;
}
render() {
return <div>{this.props.name}</div>;
}
}
在上述示例中,只有当 name 属性发生变化时,组件才会重新渲染。如果 name 保持不变,即使其他属性或状态发生变化,组件也不会重新渲染。
PureComponent
PureComponent 是 React 中的一个组件基类,它与 Component 类似,但有一个重要的区别:PureComponent 实现了一个浅比较 (shallow comparison) 在其 shouldComponentUpdate 生命周期方法中,用于比较组件的 props 和 state。
浅比较 (Shallow Comparison):
浅比较指的是在比较两个值时,只比较它们的顶层结构,而不会递归地深入每个层级。例如,当比较两个对象时,浅比较只检查对象的顶级属性是否相同,而不会检查这些属性的子属性是否也相同。
为什么使用 PureComponent?
React 的重渲染不总是有害的或特别昂贵的,但在某些场景中,不必要的重渲染可能会导致性能问题。PureComponent 可以帮助我们避免这些不必要的渲染,从而提高应用程序的性能。
当组件的 props 或 state 发生改变时,PureComponent 会执行浅比较,如果没有任何变化,则跳过渲染。这对于那些很少或从不更改其 props 或 state 的组件来说,可能是一个很好的性能优化。
注意点:
-
不总是合适: 由于
PureComponent只执行浅比较,所以它可能不适合深层嵌套的对象结构。在这种情况下,即使数据实际上没有改变,浅比较也可能认为数据已经改变,因为顶层对象/数组引用可能已经改变。 -
不要更改原始数据: 使用
PureComponent时,应避免直接修改props或state。而是应该总是返回新的对象或数组。 -
与函数组件的
React.memo: 对于函数组件,React 提供了React.memo,它的作用与PureComponent类似,可以避免不必要的渲染。
示例:
class MyPureComponent extends React.PureComponent {
render() {
return <div>{this.props.name}</div>;
}
}
在上述示例中,只有当 props.name 真正发生改变时,MyPureComponent 才会重新渲染。如果其他 props 发生变化,但 name 保持不变,那么组件不会重新渲染。