如何基于字符串ID用Angular NgRx删除数据并正确实现Effect
问题解答
1. 调用删除接口的位置选择
- 你提到的在组件中先调用接口再dispatch action的写法技术上可以运行,但不符合NgRx的设计规范:所有副作用(API请求、IO操作等)都建议统一放到Effect中管理,这样可以把业务逻辑和视图逻辑分离,后续新增loading状态、失败重试、错误提示等需求时维护成本更低。
- 你当前的实现属于「乐观更新」:不等后端返回就先修改UI状态,好处是响应快,但如果后端删除失败会出现UI和后端数据不一致的问题,建议补充失败处理逻辑。
2. Effect 报错原因及修复方案
你拿到的是对象而非ID字符串,是因为ofType筛选后返回的是完整的Action对象,而非你定义的props参数本身,正确的Effect写法如下:
// 首先调整成功Action的定义,传入需要的customerID参数 export const deleteSingleCustomerActionSuccess = createAction( ActionTypes.DeleteCustomerSuccessAction, props<{ customerID: string }>() ); // 新增可选的失败Action,用于错误处理 export const deleteSingleCustomerActionFail = createAction( ActionTypes.DeleteCustomerFailAction, props<{ error: Error }>() ); // 修正后的Effect逻辑 deleteCustomersActionEffect = createEffect( () => this.actions$.pipe( // 直接传入createAction创建的action实例,不要传type字符串,能自动推断类型 ofType(deleteSingleCustomerAction), // 解构action对象拿到customerID mergeMap((action) => this.customerService.removeCustomberById(action.customerID) .pipe( map(() => deleteSingleCustomerActionSuccess({customerID: action.customerID})), // 补充catchError处理接口失败的情况,抛出删除失败的action catchError((err) => { console.error('删除客户失败', err); return of(deleteSingleCustomerActionFail({error: err})); }) ) ), tap(() => console.log(`${ActionTypes.DeleteCustomerAction} - Action Dispatched`)) ) );
3. Reducer 逻辑修正建议
你当前的Reducer在接收到删除触发action时就直接移除了state中的客户数据,建议调整为等删除成功后再修改数据,避免接口失败时数据不一致:
// 删除触发时只修改loading状态 on(deleteSingleCustomerAction, (state) => ({ ...state, loading: true })), // 删除成功后再过滤客户数据 on(deleteSingleCustomerActionSuccess, (state, {customerID}) => ({ ...state, loading: false, customers: state.customers.filter(element => element.id !== customerID) })), // 删除失败的处理,重置loading、存储错误信息 on(deleteSingleCustomerActionFail, (state, {error}) => ({ ...state, loading: false, errorMsg: error.message }))
额外提示
你Service中的方法名removeCustomberById存在拼写错误(应为removeCustomerById,少了字母s),注意检查避免调用时报错。
内容的提问来源于stack exchange,提问作者Tristate
相关产品推荐
相关产品推荐

