使用带有动态参数的 createSelector 进行反应

问题描述 投票:0回答:1

我创建了选择器来获取用户列表,如下所示:

const selectGroup = (state) => state.group;

const selectGroupUsers = createSelector(
  [selectGroup],
  (group) => group.get('users').toJS()
)

我的使用方法如下:

const users = useSelector(selectGroupUsers);

这些工作正常。

现在我尝试使用动态路径获取特定的用户信息:

const selectUser = createSelector(
  [selectGroup, (_, path)],
  (group, path) => group.getIn(path).toJS()
)

我的使用方法如下:

const path = ['users', 5, 'data'] // this is a dynamic array value from props

const userData = useSelector(state => selectUser(state, path));

这可行,但是我收到很多 redux 警告:

使用相同的选择器调用时,未知选择器返回不同的结果 参数。这可能会导致不必要的重新渲染。

我该如何解决这个问题?

我尝试按如下方式拆分选择器,但没有成功:

const selectGroup = (state) => state.group;

const selectPath = (state, path) => path;

const selectUser = createSelector(
  [selectGroup, selectPath],
  (group, path) => group.getIn(path).toJS()
)

** 更新

我重写了逻辑:

const selectUser = (path) => {
  return createSelector(
     [selectGroup, () => path],
     (group, path) => group.getIn(path).toJS()
  )
}

然后:

const userData = useSelector(selectUser(path));

这似乎有效!错误/警告消失了。我不知道为什么。这是正确的模式吗?

javascript reactjs redux immutable.js
1个回答
0
投票

[selectGroup, selectPath]
[selectGroup, (_, path) => path]
应该 有效,但这取决于
path
的值,因为这通常仅适用于基元。

您似乎正在传递一个数组,如果您将

path
重新声明为一个新的
['users', 5, 'data']
数组引用每个渲染周期,那么这将导致输入选择器每次更改并触发
selectUser
选择器函数每次都重新计算。

如果你想使用:

const selectUser = createSelector(
  [selectGroup, (_, path) => path],
  (group, path) => group.getIn(path).toJS()
);

然后我建议尝试记住传递给选择器的

path
值。这可能适合你。

示例:

const path = React.useMemo(() => {
  return ['users', 5, 'data'];
}, [/* whatever the appropriate dependencies are */]);

const userData = useSelector(state => selectUser(state, path));

或者,您可以将

path
数组值分解为可以正确记忆的各个参数。

示例:

const selectUser = createSelector(
  [
    selectGroup,
    (_state, users) => users, // users string
    (_state, _users, value) => value, // value number
    (_state, _users, _value, data) => data, // data string
  ],
  (group, users, value, data) => group.getIn([users, value, dat]).toJS()
);
const userData = useSelector(
  state => selectUser(state, 'users', 5, 'data')
);
© www.soinside.com 2019 - 2024. All rights reserved.