EasyPeasy store hook任意状态变更触发重渲染,如何保留原语法修复?
问题根因
该重渲染问题由Redux选择器的默认比较逻辑导致:
useTypedState(即Redux封装的useSelector)默认采用引用相等判断是否需要触发组件更新- 原
useGroupState返回整个groups根对象,只要groups下任意属性(status/error等)更新,根对象的引用就会发生变化 - 哪怕组件仅解构使用
ids字段,只要根对象引用变化,就会触发重渲染
解决方案
以下两种方案均可完全保留const { ids } = useGroupState()的原有调用语法,同时解决不必要重渲染问题:
方案1:Proxy细粒度缓存(推荐)
采用Redux官方推荐的proxy-memoize工具封装选择器,它会追踪返回对象上实际被访问的属性,仅当被访问过的属性发生变化时才会更新返回值的引用:
import { memoize } from 'proxy-memoize'; import { useTypedState } from './你的redux配置路径'; // 封装带缓存的groups选择器 const selectGroups = memoize((state) => state.groups); export const useGroupState = () => useTypedState(selectGroups);
该方案的优势是性能最优:如果组件仅使用ids字段,status、error等其他字段更新时,selectGroups会直接返回之前缓存的根对象引用,不会触发组件重渲染。如果项目中有大量同类型模型hook,还可以把该逻辑封装成通用工厂函数,批量生成所有模型的hook。
方案2:浅比较降级方案
如果不想引入额外依赖,且你的groups下字段数量少且固定,可以修改useTypedState的比较逻辑为浅比较:
import { shallowEqual } from 'react-redux'; import { useTypedState } from './你的redux配置路径'; export const useGroupState = () => useTypedState(state => state.groups, shallowEqual);
注意:该方案仅能避免「属性值未变但根对象引用变化」导致的无意义重渲染,如果组件仅使用
ids,status更新还是会触发重渲染,性能弱于方案1。
内容的提问来源于stack exchange,提问作者KwehDev
相关产品推荐
相关产品推荐

