最近在学习react-native发现其中的FlatList,SectionList在官方文档中都有一个共同的特点其都为纯组件,这意味着如果其props在浅比较中是相等的,则不会重新渲染。所以请先检查你的renderItem函数所依赖的props数据(包括data属性以及可能用到的父组件的 state),如果是一个引用类型(Object 或者数组都是引用类型),则需要先修改其引用地址(比如先复制到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。
纯组件(React.PureComponent)
纯组件和普通组件的区别为 shouldComponentUpdate()的实现与否,纯组件实现了,普通组件没有实现。React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。
浅比较
深入探索了一下浅比较的源码实现。浅比较主要判断两个值是否相等,在纯组件中是判断前一次的props和state与后一次的是否相同。进行比较的核心函数是采用object.is() 这个方法。
Object.is() 方法判断两个值是否为同一个值。如果满足以下条件则两个值相等:
- 都是 undefined
- 都是 null
- 都是 true 或 false
- 都是相同长度的字符串且相同字符按相同顺序排列
- 都是相同对象(意味着每个对象有同一个引用)
- 都是数字且
- 都是 +0
- 都是 -0
- 都是 NaN
- 或都是非零而且非 NaN 且为同一个值 与== 运算不同。 == 运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将 "" == false 判断为 true), 而 Object.is不会强制转换两边的值。
与=== 运算也不相同。 === 运算符 (也包括 == 运算符) 将数字 -0 和 +0 视为相等 ,而将Number.NaN 与NaN视为不相等.
并且在shouldComponentUpdate()中官方也不建议进行深层比较或使用 JSON.stringify()。这样非常影响效率,且会损害性能。
只要存在浅比较的话就注意参数类型,如果为引用类型需要注意。
性能优化
react中存在很多性能优化的api,比如
React.memo这个高阶组件。
默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。这里就存在了浅比较,所以要注意传入参数是否为引用类型了。
useMemo
把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。这里的第二个参数的比较也是浅比较,所以要注意参数的类型。
useCallback
把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。这里的第二个参数的比较也是浅比较,所以要注意参数的类型。
这些性能优化的前提都会遵循浅比较的逻辑,要格外注意其参数格式