reactjs - React useSelector hook 是传播对象还是只指定需要的字段更好
问题描述
如果我有一个巨大的对象(40 多个字段)并且我在组件中调用 useSelector 但只需要此类对象的 3 个字段,那么只调用 3 个字段会更好:
const user = useSelector((state) => ({
id: state.userReducer.id,
name: state.userReducer.name,
lastName: state.userReducer.lastName
}));
在这种情况下还可以,因为我们只需要 3 个字段,但如果我们需要 10+ 个字段,事情就会变得非常冗长。在这种情况下,扩展运算符可以为我节省大量代码,但这是一种不好的做法吗?由于代码混淆,性能或其他原因?
const user = useSelector((state) => ({ ...state.userReducer }));
解决方案
出于性能原因,您应该这样做:
const user = useSelector(state => state.userReducer);
您的选择器将在分派操作时运行。如果它返回不同的东西,那么在最后一次运行时,它将强制组件重新渲染。通过传播到一个新对象,它总是会返回一个新对象。因此,您的组件将在每个被调度的操作上重新渲染。
useSelector()
还将订阅 Redux 存储,并在分派操作时运行您的选择器。[...]
当一个动作被调度时,
useSelector()
会对之前的选择器结果值和当前的结果值做一个参考比较。如果它们不同,组件将被强制重新渲染。[...]
useSelector()
默认情况下使用严格===
的引用相等检查,而不是浅相等
我也觉得钥匙userReducer
有点尴尬。它只是user
不是用户的减速器。reducer 是一个纯函数,它将动作转换为更改而不是数据对象。
编辑:
正如@Adam 在评论中所指出的,如果您想进一步减少重新渲染的数量,您可以使用记忆选择器仅选择您感兴趣的状态。创建此类选择器的一个很好的库是reselect。
// example
import { createSelector } from 'reselect';
const basicUserDataSelector = createSelector(
({user}) => user.id,
({user}) => user.name,
({user}) => user.lastName,
(id, name, lastName) => ({id, name, lastName})
);
// usage
const user = useSelector(basicUserDataSelector);
在您的情况下,仅选择所需状态的最简单方法是告诉useSelector
进行浅相等比较而不是参考相等比较。useSelector
接受比较器函数作为第二个参数:
import { shallowEqual, useSelector } from 'react-redux'
const user = useSelector(
({user}) => ({
id: user.id
name: user.name
lastName: user.lastName
}),
shallowEqual
);
最佳实践是仅从存储中提取所需的尽可能少的数据以限制重新渲染的数量。选择更多实际需要的数据的额外成本取决于所选数据的组件和更改频率。
推荐阅读
- android - 印象笔记安卓作业
- elixir - mix deps.get: Hex 安装到错误的 elixir 版本中
- php - 使用正则表达式针对 PHP 中未编码的字符验证编码的 URI
- angular - 无法在角度 4 中使用 ngForm - 出现未定义的错误
- exception - 扩展面板底部溢出
- generative-adversarial-network - 任何用于 GAN 的异步训练方法?
- ios - 嵌套的 UITableView 返回单元格但不显示它
- ubuntu - 挂载 NFS 时访问被拒绝
- kotlin - 对象不是抽象的,也没有实现抽象成员
- python - var == False 或者如果不是 var