我在不可变的 redux 状态下创建了组中的用户选择器:
import { useStore } from 'react-redux';
import { createSelector } from '@reduxjs/toolkit'
const selectGroup = (state) => state.group;
const memoizedUsers = createSelector([selectGroup], (group) => {
return group.get('users').toJS();
})
const useMemoizedUsers = () => {
const store = useStore();
return memoizedUsers(store.getState());
}
然后在我的组件中显示用户列表,并提供删除用户的选项:
const DeleteButton = ({ rowIndex )} => {
const dispatch = useDispatch();
return (
<Button onClick={() => {
dispatch({
type: '@@group/removeUser',
payload: { rowIndex }
})
}}>
Delete
</Button
)
}
const columnDefs = [
{
headerName: 'Name',
field: 'name',
},
{
headerName: 'Age',
field: 'age',
},
{
headerName: '',
field: 'onDelete',
cellRenderer: ({ node: { rowIndex } )} => {
return (
<DeleteButton rowIndex={rowIndex} />
)
}
}
];
const UserList = () => {
const users = useMemoizedUsers();
return {
<Grid
rowData={users}
columnDefs={columnDefs}
/>
}
}
当我点击删除时,我看到 redux 存储正在更新 ==> 从 10 个用户减少到 9 个用户。 但是,我的 UserList 组件没有重新渲染,UI 仍然显示所有 10 个用户。
有人知道如何强制更新组件还是我错误地使用了createSelector?
如果我更改 const 用户:
const users = useSelector((state) =>
state.group.get('users')?.toJS()
}
组件重新渲染并且用户列表更新,但我收到 redux 警告,当使用相同的参数调用时,Selectorknown 返回了不同的结果。这可能会导致不必要的重新渲染。
此外,我可以像这样重写 UserList:
const UserList = () => {
const users = useSelector((state) =>
state.group.get('users')
}
return {
<Grid
rowData={users.toJS()}
columnDefs={columnDefs}
/>
}
}
以这种方式编写组件会重新渲染 UI,并且 redux 警告会消失,但这违背了使用 createSelectors 的目的
useStore
挂钩实际上并不订阅商店的更新。 store.getState
基本上是一个一次性的函数调用,它从存储中获取并返回当前状态值一次。
const useMemoizedUsers = () => {
const store = useStore();
return memoizedUsers(store.getState()); // <-- doesn't subscribe to store changes
}
createSelector
实际上已经创建了一个记忆选择器函数,因此您只需在useSelector
钩子调用中直接使用它即可。
const selectGroup = (state) => state.group;
const selectGroupUsers = createSelector(
[selectGroup],
(group) => group.get('users').toJS()
)
import { useSelector } from 'react-redux';
...
const UserList = () => {
const users = useSelectors(selectGroupUsers);
return {
<Grid
rowData={users}
columnDefs={columnDefs}
/>
}
}