React中额外重渲染概念疑问:请求相关示例说明
什么是React里的“额外重渲染”?举个例子给你看
别担心,我给你搭个真实场景,一看就明白啥叫额外重渲染了。咱们先从有问题的代码说起,再对比优化后的效果。
有问题的场景:每次渲染都生成新回调,导致子组件额外重渲染
首先,我们写一个父组件LoggingButton,还有一个用React.memo包裹的子组件ChildButton——React.memo的作用是浅比较组件的props,只有props真正变化时才会重新渲染子组件。
import React, { memo } from 'react'; // 子组件:接收onClick作为props,每次渲染时打印日志 const ChildButton = memo(({ onClick }) => { console.log('ChildButton 被重渲染了!'); return <button onClick={onClick}>点击我</button>; }); // 父组件:用箭头函数创建回调 class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { console.log('LoggingButton 父组件渲染了'); // 每次render都会创建一个新的箭头函数 return <ChildButton onClick={(e) => this.handleClick(e)} />; } }
现在你运行这个组件,只要父组件LoggingButton触发渲染(比如父组件自身props变化、或者父组件的state更新),你会在控制台看到:
LoggingButton 父组件渲染了 ChildButton 被重渲染了!
明明子组件ChildButton的功能完全没变,只是因为父组件每次都传了一个新的箭头函数(函数引用变了),React.memo的浅比较认为props变了,所以子组件被迫跟着重新渲染——这就是我们说的额外重渲染。如果子组件是个复杂的大型组件,这种无意义的重渲染会浪费不少性能。
优化后的场景:固定回调引用,避免额外重渲染
我们改用类字段语法绑定this,这样handleClick的引用会一直保持不变,不会每次渲染都生成新函数:
import React, { memo } from 'react'; const ChildButton = memo(({ onClick }) => { console.log('ChildButton 被重渲染了!'); return <button onClick={onClick}>点击我</button>; }); class LoggingButton extends React.Component { // 类字段语法:提前绑定好this,这个函数的引用始终不变 handleClick = () => { console.log('this is:', this); }; render() { console.log('LoggingButton 父组件渲染了'); // 这里传递的是固定引用的handleClick,不是新创建的函数 return <ChildButton onClick={this.handleClick} />; } }
现在再运行,当父组件触发渲染时,控制台只会打印:
LoggingButton 父组件渲染了
子组件ChildButton不会跟着重渲染了,因为onClick的引用没变化,React.memo判断props没更新,就跳过了子组件的渲染——这就避免了额外重渲染。
简单总结下:额外重渲染就是组件在自身状态/功能不需要更新的情况下,因为传入的props(比如回调函数)引用发生了无意义的变化,被迫执行渲染流程的情况。
内容的提问来源于stack exchange,提问作者Bảo Phạm Hoàng
相关产品推荐
相关产品推荐

