Reactjs 具有id字段的重复使用选择器

Reactjs 具有id字段的重复使用选择器,reactjs,redux,react-hooks,Reactjs,Redux,React Hooks,我需要你关于用选择器过滤数据的建议。假设我的应用程序中有以下实体。1组织有多个设备,在“我的状态”形状中显示如下: state { devices: { byId: [ 1 { name: device1 } ] } organizations: { byId: [ 1 { name: org1, devices: [1,2,3] } ] } } 现在我想过滤组织内部的设备。这是我想用选择器做的事情。我的

我需要你关于用选择器过滤数据的建议。假设我的应用程序中有以下实体。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))
}
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>
    )
}
这应该可以正常工作,但是在我从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
            }
        }
    })
我的功能组件如下所示:

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))
}
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>
    )
}
功能设备(){
const dispatch=usedpatch();
常量设备=使用选择器(选择组织设备(1))
useffect(()=>{
调度(fetchOrganizationDevices(1))
}, [])
常量列=[]
返回(
)
}

我现在得到的错误是
organization.devices未定义
,表示状态中的设备数组为空。似乎在分派之前调用了useSelector。如何防止重复执行此操作?或者应该在我的代码中更改什么?

是的,
useffect
钩子在第一次渲染后运行<代码>使用选择器将在第一次渲染期间运行。因此,您的组件代码需要安全地处理数据还不存在的情况

另外,不要将硬编码的数组/对象文本放入这样的选择器中,因为它每次都是一个新引用,并在每次调度操作时强制组件重新渲染。将其提取到选择器外部的常量,或者使用诸如“重新选择”之类的记忆库来创建选择器


最后,您应该使用,其中包括简化几个常见Redux用例的实用程序,包括存储设置、定义缩减器、不可变更新逻辑,甚至一次创建整个状态“切片”。它还有一个新的
createEntityAdapter
API,可以帮助您管理商店中的规范化状态。

试试
return organization.devices?org.devices.map(id=>selectDevice(id)(state)):[]
我不知道
createEntityAdapter
API。非常感谢你的支持和帮助!