如果 useSelector 返回的 state 数据很大,可能会导致 不必要的组件重新渲染,影响性能。优化方式主要有以下几种:
1. 精确选择数据,避免返回整个对象
❌ 错误做法(返回整个 state 对象)
⚠️ 问题:
- 任何 state.bigData 内部的字段变化都会触发组件重新渲染,即使组件只用到其中一部分数据。
✅ 正确做法(只选择需要的字段)
✅ 优势:
- 组件只会在 someValue 变化时重新渲染,而不会因 bigData 的其他字段变化而重新渲染。
2. 使用 reselect 进行 Memoization
如果计算 state 需要进行复杂的计算(如 filter、map 等),可以使用 reselect 缓存计算结果。
📌 安装 reselect
📌 创建 selector
📌 组件中使用 selector
✅ 优势:
- createSelector 只有在 state.bigData 变化时才会 重新计算,否则返回缓存结果。
- 避免不必要的计算,提升性能。
3. useSelector 第二个参数 equalityFn 自定义比较
默认情况下,useSelector 使用 浅比较(===) 来判断状态是否变化。如果 state 是 深层对象,可以使用 自定义比较函数 进行优化。
📌 默认 useSelector(浅比较,可能会导致不必要的渲染)
📌 使用 shallowEqual 进行浅层对比
✅ 优势:
- shallowEqual 仅在 bigData 的 顶层字段 发生变化时才触发组件重新渲染。
📌 自定义 equalityFn(仅在 id 变化时更新)
✅ 优势:
- 避免 bigData 其他字段变化时,导致不必要的重新渲染。
4. 拆分 state,减少 store 更新影响范围
如果 bigData 很大,可以考虑拆分 store 结构,让 Redux 多个 slice 管理不同部分的数据。
📌 优化前(单个 slice 存放大量数据)
📌 优化后(拆分成多个 slice)
📌 组件按需获取 state
✅ 优势:
- 避免 bigData 变化时,所有依赖 bigData 的组件都重新渲染。
5. 组件拆分,减少渲染范围
如果 useSelector 获取的数据很大,考虑 拆分组件,让子组件只订阅需要的数据。
📌 错误示例(整个组件订阅大数据)
📌 优化示例(拆分成子组件,每个子组件独立订阅状态)
✅ 优势:
- 只有受影响的 ListItem 组件会重新渲染,而不是整个 ParentComponent。
6. 结合 useMemo 进行优化
如果 useSelector 返回的数据需要复杂计算,可以用 useMemo 缓存结果,避免重复计算。
📌 错误示例(计算逻辑直接在 useSelector 内部)
📌 优化示例(用 useMemo 缓存计算结果)
✅ 优势:
- useMemo 只有在 data 变化时才会重新计算,提高性能。
🚀 总结
优化方法 | 思路 | 适用场景 |
1. 精确选择数据 |
只返回 需要的字段,而不是整个 | 适用于 |
2. 使用 |
缓存计算结果,避免重复计算 | 适用于 依赖计算、列表过滤 场景 |
3. 自定义 | 只在 关键数据变化 时触发渲染 | 适用于 深层数据结构 |
4. 拆分 | 将 | 适用于 大规模应用 |
5. 组件拆分 | 让子组件独立订阅 | 适用于 列表渲染、大数据量场景 |
6. | 避免 | 适用于 复杂计算 |
📌 最终优化思路:
- 尽量让 useSelector 只选择最小数据。
- 使用 reselect 避免不必要的计算。
- 尽量拆分组件,减少不必要的渲染。
这样可以让 react-redux 更高效地更新 UI,提升应用性能! 🚀