背景:
需求有个门店选择组件,样式如下。 实现方式为 React Hooks。

问题: QA同学测试后表示实际线上商户选择门店时,门店数可达6000~1w, 在这样的情况下组件比较卡, 难以使用
解决
这就是 大数据列表时展示与渲染问题了, 推荐 useVirtualList 这个Hook , 很好用~~
使用虚拟列表实现是主要的解决方案 , 但我还是想就这个场景 看下我的Hook 使用是否有异常渲染,是否写法上有优化方式。
工具查看
1、 Chrome 调试工具- Paint Flashing 功能,可以将发生改变的 DOM 高亮显示。
2、相同的功能在 React 调试工具为Highlight Updates,可以在 React 调试工具的首选项面板中找到它。激活后,它会高亮显示所有正在渲染的组件。如果渲染时间过长,它还会用特殊颜色标识出来。



诊断结论: 使用上述工具分析 页面渲染正常, 页面卡顿 主因还是 DOM 节点太多,导致render时间太长,使用虚拟列表解决

结果

相关知识
1、React 使用虚拟 DOM 来代表 DOM 中真实的元素。每当用户操作界面元素,应用的 state 都会改变。React 会遍历所有受 state 改变影响的组件,计算生成新的虚拟 DOM。React 将新旧版本的虚拟 DOM 进行比较,若发现二者有差异,就将对应的变化更新到真实 DOM 上。该过程叫做 reconciliation
2、常见Hooks 性能优化方案
-
useMemo
会记忆一个值,这样就不用在下一轮渲染中重新计算它了;useCallback
记忆的则是回调函数。你可以给二者传入一个依赖数组,该数组包含了组件作用域的值(比如 props 和 state),这些值将在 hooks 内部被用到。每次渲染时,React 都会比较这些依赖值,一旦它们发生改变,React 就会更新备忘的值或函数。
场景1:
function handleChange(value => {
...
});
<Parent
value={[minValue, maxValue]}
onChange={handleChange}
/>
应改为:
const handleChange = useCallback((value) => {
...
}, []);
const value = useMemo(() => [minValue, maxValue], [minValue, maxValue]);
<Parent
value={value}
onChange={handleChange}
/>
场景2 :
const complexComplet = (value) => { }
const Parent = (props) => {
const initAge = complexComplet(props.value)
const { age, setAge} = useState(initAge) // 经复杂计算 得到初始化的值
}
经复杂计算 得到初始化的值, 此场景在组价Render时 complexComplet 也会重新计算, 故应改为:
const complexComplet = () => { }
const Parent = (props) => {
const initAge = useMemo(() => complexComplet(props.value), [props.value])
const { age, setAge} = useState(initAge) // 经复杂计算 得到初始化的值
}
- React.memo: 当用 React.memo 包裹一个函数组件时,它会将传入的 props 进行浅层比较。当比较的 props 不一致时,才会重新渲染组件。也可以自己写一个比较函数,作为第二个参数传入。
我们可以将组件分解为更小的组件,并把每个更小的组件都用 React.memo 包裹起来。如此你能保证当 props 更新,仅有组件的一部分重新渲染了。但也不要把所有东西都做memo,因为比较 props 所花时间可能要比渲染组件的时间还要长。
const Parent = React.memo((props) => {
const initAge = useMemo(() => complexComplet(props.value), [props.value])
const { age, setAge} = useState(initAge)
})
参考文档
hi~~ 今天的你点赞了嘛~
网友评论