📖 “停止 React 中不必要的重新渲染组件!!”的历史记录
很久很久以前……
💎 生成类组件
🚩 纯组件()
比较新旧 props/state,如果它们之间存在差异,则组件渲染
比较??但是如何比较它们呢?
<< React 中渲染的情况 >>
- 状态改变
- 父组件渲染
- 道具变化
- shouldcomponentUpdate 函数返回 true (稍后我会解释)
- 强制更新
对于数字 1 和 2,React 决定是否通过浅比较进行渲染
什么是浅比较?
首先,我们需要了解 一下这个网站是什么

-
通过引用传递(浅拷贝)
如果你将咖啡倒入复制的杯子中,那么原始杯子也会被装满(因为两个数据都在相同的内存分配空间中) -
按值传递(深层复制)
如果你将咖啡倒入复制的杯子中,原始杯子仍然是空的
在 Javascript 中,原始数据类型(String、Number、Bigint、Boolean、Undefined、Symbol)通过值传递,而 Object、Array 通过引用传递
老实说,与原始数据类型进行比较并不困难,但我们需要关心与 Object 的比较
对象引用的情况也一样
import shallowCompare from 'react-addons-shallow-compare';
const a = { country: "poland", country2: "japan" }
const b = a
console.log(shallowEqual(a, b))
// true
对象引用的情况不同
- 非嵌套对象
import shallowCompare from 'react-addons-shallow-compare';
const a = { country: "poland", country2: "japan" }
const b = { country: "poland", country2: "japan" }
console.log(shallowEqual(a, b))
// true
- 嵌套对象
import shallowCompare from 'react-addons-shallow-compare';
const a = {
country: "poland",
coountry2: {
city1: "tokyo",
city2: "osaka"
}
}
const b = {
country: "poland", // country is primitive type, scalar data is the same -> true
country2: { // country2 is object, so reference is different -> false
city1: "tokyo",
city2: "osaka"
}
}
console.log(shallowEqual(a, b))
// ⭐ false
🚩 shouldComponentUpdate()
👦 所以所有组件都是纯组件就没问题了,不是吗?
👩💻 不行,因为比较新旧 state/props 的成本很高
👦 那我该怎么办?
👩💻 直接通过“shouldComponentUpdate()”自行决定比较条件就行了。
实际上 PureComponent 就像是由某人(可能是 Facebook 公司的某个人)通过 shouldComponentUpdate() 实现的组件
// something like that
class PureComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return !(shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState));
}
…
}
💎 函数组件生成
2022年我们处于这一代
🚩 React.memo
它就像 PureComponent() + shouldComponentUpdate()
// if new props changes, this component will be rendered
const Button = React.memo(props => {
return <div>{props.value}</div>
})
// if you put second argument, it is like shouldComponentUpdate()
const Button = React.memo(
props => {
return <div>{props.value}</div>
},
(nextProps, prevProps) => {
return nextProps.value === prevProps.value
}
)
🚩 useMemo
👦 useMemo 是什么?它和 React.memo 一样吗?
👩💻 不一样,其实很像。React.memo 是 React 16.6 版本新增的,之后 React hook 16.8 版本也新增了 useMemo。👦
啊哈
👩💻 useMemo 只会在 props 发生变化时渲染,因为它会记住计算结果。
// when only "products props" changes, this component renders
const Component: React.FC = ({ products }) => {
const soldoutProducts = React.useMemo(() => products.filter(x => x.isSoldout === true), [products])
}
🚩 useCallback
当父组件将函数的 props 传递给子组件时,会创建一个新的函数(实际上函数只是对象之一)。
因此,子组件会识别出这个新的函数与旧函数不同,然后悲伤地重新渲染。
↓ 子组件/父组件之间的对话
👨 父级「重新渲染!!现在我重新创建了我已有的函数!!」
👼 子级「妈妈!!把你的函数作为 props 给我!!」
👨 父级「好的,我把我的函数给你!」
👼 子级「好吧,现在我需要确认这个对象的内存地址是否与我之前获得的对象相同……嗯,地址不同,我也重新渲染了!!!」
为了防止这种不必要的重新渲染,应该使用 useCallback
文章来源:https://dev.to/kaziusan/history-of-stop-unnecessary-re-rendering-component-in-react--146f