Redux useSelector with id field



我需要你关于使用选择器过滤数据的建议。假设我的应用程序中有以下实体。1 组织有多个设备,这些设备在我的状态形状中如下所示:

state {
devices: {
byId: [ 1 { name: device1 } ]
}
organizations: {
byId: [ 
1 { name: org1, devices: [1,2,3] } 
]
}
}

现在,我想筛选组织内的设备。这是我想用选择器做的事情。我的选择器如下所示:

const selectDevice = (id: any) => (state: State) => state.devices.byId[id]

export const selectOrganizationDevices = (id: number) => (state: State) => {
const organization = state.organizations.byId[id] || []
return organization.devices.map(id => selectDevice(id)(state))
}

这应该工作正常,但是在我从redux调度数据之前,我的选择器被调用了。我想我的减速器或我创建的组件有问题。

我的减速器看起来像这样:

return produce(state, draftState => {
switch (action.type) {
...
case OrganizationActionTypes.FETCH_DEVICES_SUCCESS: {
draftState.byId = action.payload.entities.organizations
draftState.allIds = Object.keys(action.payload.entities.organizations)
draftState.loading = false
break;
}
...
default: {
return state
}
}
})

我的功能组件如下所示:

function Devices() {
const dispatch = useDispatch();
const devices = useSelector(selectOrganizationDevices(1))
useEffect(() => {
dispatch(fetchOrganizationDevices(1))
}, [])
const columns = []

return (
<Layout headerName={"Devices"}>
<Table dataSource={devices} columns={columns}/>
</Layout>
)
}

我现在得到的错误是organization.devices is undefined它说处于状态的设备数组为空。似乎在调度之前调用了useSelector。如何防止重复执行此操作?或者我的代码中应该更改什么?

是的,useEffect钩子在第一次渲染运行。useSelector将在第一次渲染期间运行。 因此,组件代码需要安全地处理该数据尚不存在的情况。

此外,不要将硬编码的数组/对象文本放在这样的选择器中,因为它每次都会成为一个新的引用,并强制您的组件在每次调度操作时重新渲染。 要么将其提取到选择器外部的常量,要么使用记忆库(如 Reselect(来创建选择器。

最后,您应该使用我们的官方 Redux 工具包包,其中包括用于简化几个常见 Redux 用例的实用程序,包括存储设置、定义化简器、不可变更新逻辑,甚至一次创建整个状态"切片"。 它还具有新的createEntityAdapterAPI,可帮助您管理存储中的规范化状态。

相关内容

最新更新