如何避免useSelector钩子触发的React组件不必要重渲染
你当前的代码存在两个核心问题
useSelector用法错误:回调函数自带最新的state参数,不需要手动调用store.getState()获取数据,会增加额外的引用判断风险- 数据处理流程冗余:你把selector取数、格式转换、本地state存值拆成了三步,每一步都可能触发额外渲染
useSelector默认通过===严格比较返回值的引用是否变化,只要返回值引用不变,就不会触发组件重渲染。你当前的三次渲染完全可以通过优化流程减少到1~2次,大部分场景下可以完全消除不必要的重渲染。
优化方案1:合并数据处理逻辑到useSelector(推荐,可直接消除第三次渲染)
直接把格式矫正逻辑放到useSelector回调中,搭配浅比较判断返回值是否变化,不需要额外用useEffect+useState中转数据:
首先从react-redux导入浅比较工具:
import { useSelector, shallowEqual } from 'react-redux'
然后改写取数逻辑:
// 直接返回转换完成的表格数据,不需要中转 const tableData = useSelector(state => { let sourceList = [] if (type === 'catalog') { sourceList = state.catalog.products } else if (type === 'category') { sourceList = state.categories.categories } // 直接在selector中完成格式转换 return sourceList.map(product => ({ _prodid: product?._id, image: product?.catalogProduct?.image, category: product?.catalogProduct?.category.name, name: product?.catalogProduct?.name, pricePerPiece: product?.catalogProduct?.pricePerPiece, pricePerPackage: product?.catalogProduct?.pricePerPackage, address: product?.address, piecesAtStorage: product?.piecesAtStorage })) }, shallowEqual) // 浅比较数组内容,只有真实数据变化时才触发重渲染
改完后可以直接删掉原来的useEffect和存储转换数据的useState,直接用tableData渲染表格即可,第三次setData触发的渲染会直接被消除。
优化方案2:完全屏蔽useSelector的重渲染(极端场景用)
如果你确实不需要响应store的变化,可以直接调用store.getState()在需要的时候主动取数,不需要用useSelector,自然不会触发selector相关的重渲染。但这种方式会丢失数据响应性,非特殊需求不推荐使用。
内容的提问来源于stack exchange,提问作者Evgeny Alekseev
相关产品推荐
相关产品推荐

