我有两个模型,一对多关系:
export interface GroupModel {
id: number;
name: string;
userIds?: number[];
}
export interface UserModel {
id: number;
name: string;
groupId?: number;
}
问题是,当我用效果更新其中任何一个时,更改不会反映在相应的关联中:
groups.effects.ts
updateGroup$ = createEffect(() =>
this.actions$.pipe(
ofType(GroupsActions.updateGroup),
concatMap(({ group }) =>
this.groupsService.update(group).pipe(
map(() =>
GroupsAPIActions.groupUpdatedSuccess({
update: { id: group.id, changes: group },
})
),
catchError((error) =>
of(GroupsAPIActions.groupUpdatedFail({ message: error }))
)
)
)
)
);
users.effects.ts
updateUser$ = createEffect(() =>
this.actions$.pipe(
ofType(UsersActions.updateUser),
concatMap(({ user }) =>
this.usersService.update(user).pipe(
map(() =>
UsersAPIActions.userUpdatedSuccess({
update: { id: user.id, changes: user },
})
),
catchError((error) =>
of(UsersAPIActions.userUpdatedFail({ message: error }))
)
)
)
)
);
我的减速器更新方法如下所示:
on(
GroupsActions.groupStation,
(state) =>
({
...state,
loading: true,
errorMessage: '',
})
),
on(GroupsAPIActions.groupUpdatedSuccess, (state, { update }) =>
groupsAdapter.updateOne(update, {
...state,
loading: false,
})
),
on(
GroupsAPIActions.groupUpdatedFail,
(state, { message }) =>
({
...state,
loading: false,
errorMessage: message,
})
)
总而言之,我们有以下模型:
groups: [
{ id: 1, name: "Group 1", userIds?: [1, 2] }
];
users: [
{ id: 1, name: "User 1", groupId: 1 }
{ id: 2, name: "User 2", groupId: 1 }
];
然后我调用调度方法,我们想要从组中删除用户 2:
this.store.dispatch(UserActions.updateUser({
user: { id: 2, name: "User 2", groupId: undefined }
});
我希望第 1 组也从
userId
数组中删除 userIds
:
{ id: 1, name: "Group 1", userIds?: [1] }
实现这一目标的好方法是什么?是否有标准方法或者我需要编写代码来手动处理这个问题?
编辑:
我为
groupsReducer
手动编写了以下代码,但这对于如此琐碎的任务来说似乎有很多代码。
on(UsersAPIActions.userUpdatedSuccess, (state, { update }) => {
const userId = +update.id;
const newGroupId = update.changes.groupId;
const allGroups = selectAll(state);
console.log(update);
// Find the group that contains the userId
const groupToUpdate = allGroups.find((group: GroupModel) =>
group.userIds.includes(userId)
);
const updateGroupChanges = {} as Partial<GroupModel>;
// Group is found
if (groupToUpdate) {
// UpdatedUser has a group
if (newGroupId) {
// A: If the group is the same: do nothing
if (groupToUpdate.id === newGroupId) return state;
// B: If the group is different, remove the user from the old group and add it to the new one
const oldGroupChanges = {
userIds: groupToUpdate.userIds.filter(
(id) => id !== newGroupId
),
} as Partial<GroupModel>;
const newGroupChanges = {
userIds: [...groupToUpdate.userIds, newGroupId],
} as Partial<GroupModel>;
console.log(
`Group ${groupToUpdate.id}: Moving user ${userId} to group ${newGroupId}`
);
return groupsAdapter.updateMany(
[
{ id: groupToUpdate.id, changes: oldGroupChanges },
{ id: newGroupId, changes: newGroupChanges },
],
{ ...state }
);
}
// UpdatedUser has no group: Remove group
console.log(`Group ${groupToUpdate.id}: Removing user ${userId}`);
updateGroupChanges.userIds = groupToUpdate.userIds.filter(
(id) => id !== newGroupId
);
} else {
// No group is found
// UpdatedUser has no group: Do nothing
if (!newGroupId) return state;
// UpdatedUser has a group: Add user to a group
const newGroup = selectGroupById(newGroupId)(state);
if (!newGroup) {
console.warn(
`Group ${newGroupId}: Not found! Could not add user ${userId}`
);
return state;
}
console.log(`Group ${newGroupId}: Adding user ${userId}`);
updateGroupChanges.userIds = [...newGroup.userIds, userId];
}
return groupsAdapter.updateOne(
{
id: newGroupId,
changes: updateGroupChanges,
} as Update<GroupModel>,
{ ...state } satisfies GroupsEntityState
);
}),
为了更新这两个状态,reducers 将监听这两个操作来更新自己的状态。
例如。减少的小组将聆听
groupUpdatedSuccess
(就像现在一样),也会聆听行动userUpdatedSuccess
。
这同样适用于用户减速器,它监听
userUpdatedSuccess
和 groupUpdatedSuccess
操作。