为NgRx Signal Store的withEntities配置自定义主键
NgRx Signal Store withEntities 指定自定义主键(fruitId)的解决方案
问题场景
我在用NgRx Signal Store的withEntities管理水果实体时遇到了问题:withEntities默认要求实体类必须包含id字段作为主键,但我的Fruit类是OpenAPI自动生成的,仅拥有fruitId字段且无法修改。不想给每个实体手动添加重复的id字段,请问能否直接指定fruitId作为Store的主键?
当前Store代码:
export const FruitStore = signalStore( { providedIn: 'root' }, withEntities<Fruit>(), withMethods(( store, fruitService = inject(FruitService), ) => ({ loadFruits: rxMethod<void>( pipe( exhaustMap(() => { return fruitService.getFruits().pipe( tapResponse({ next: (fruits) => { patchState(store, setAllEntities(fruits)); }, error: (error: { message: string }) => { console.log(error.message); } }), ); }), ) ), })), withHooks({ onInit({ loadFruits }) { loadFruits(); } }), );
Fruit类代码:
export class Fruit { fruitId: number; name: string; imageURL: string; }
优化解决方案
当然可以!NgRx Signal Store的withEntities支持通过配置项指定自定义主键,无需额外扩展类型或添加重复字段。只需在调用withEntities时传入selectId选项,指定用fruitId作为实体的唯一标识即可。
修改后的完整Store代码:
export const FruitStore = signalStore( { providedIn: 'root' }, // 配置selectId,指定fruitId作为实体主键 withEntities<Fruit>({ selectId: (fruit) => fruit.fruitId }), withMethods(( store, fruitService = inject(FruitService), ) => ({ loadFruits: rxMethod<void>( pipe( exhaustMap(() => { return fruitService.getFruits().pipe( tapResponse({ next: (fruits) => { // 无需再手动添加id字段,直接传入原始API返回数据 patchState(store, setAllEntities(fruits)); }, error: (error: { message: string }) => { console.log(error.message); } }), ); }), ) ), })), withHooks({ onInit({ loadFruits }) { loadFruits(); } }), );
方案说明
selectId函数接收实体实例,返回其唯一标识值,这里直接返回fruit.fruitId即可- 配置后,Store内部会用
fruitId跟踪实体唯一性,完全替代默认的id字段 - 无需再对API返回数据做
map转换添加冗余的id字段,保持数据结构与API一致
内容的提问来源于stack exchange,提问作者Levente Vági
相关产品推荐
相关产品推荐

