CreateEntityAdapter与normalizr默认兼容吗?SelectId总是返回undefined
关于createEntityAdapter搭配normalizr使用时selectId的问题解答
核心结论
是否需要自定义selectId函数取决于你的使用方式,不存在强制要求。
默认selectId的逻辑
createEntityAdapter内置的默认selectId函数逻辑非常简单:直接返回传入实体对象的id属性,也就是entity => entity.id。只要传入的实体对象有顶层id属性,默认逻辑就能正常运行。
你遇到返回undefined的常见原因
你现在触发错误,大概率是使用方式不符合要求,可对应排查:
- 你直接把normalizr输出的
entities.对应实体类型的键值对对象(就是你示例里的{"1": {id:"1"...}, ...}结构)直接传给了addMany/setAll这类adapter内置的批量操作方法。这类方法要求入参是实体对象组成的数组,传键值对对象的话自然无法读取到id属性。
这种情况你不需要自定义selectId,只要先通过Object.values(yourNormalizrEntities)把键值对转成实体数组再传入即可。 - 如果你已经转成了数组还是返回undefined,说明你的实体唯一标识字段不是顶层
id,或者字段名不叫id,这种情况就必须自定义selectId,示例如下:// 假设你的唯一标识字段叫user_id const userAdapter = createEntityAdapter({ selectId: (userEntity) => userEntity.user_id })
特殊优化写法
因为normalizr输出的实体结构和createEntityAdapter的state内置的entities字段结构完全一致,你可以直接赋值不走adapter内置方法,连selectId都不需要调整,示例如下:
const yourSlice = createSlice({ name: 'yourEntity', initialState: yourAdapter.getInitialState(), reducers: { setNormalizedEntities: (state, action) => { // action.payload为normalizr返回的entities.对应实体类型对象 state.entities = action.payload state.ids = Object.keys(action.payload) } } })
内容的提问来源于stack exchange,提问作者Ed Campion
相关产品推荐
相关产品推荐

