Angular NGRX使用withLatestFrom实现API仅调用一次但loader仍被置为true如何解决
问题根因
你遇到的问题本质是NGRX中被分发的Action会同时传递给Reducer和Effect:
- 每次你分发
PackingPageActions.loadPackingList,监听了该Action的Reducer都会第一时间执行,将loading置为true - 而Effect中做的过滤逻辑仅会决定是否发起API请求,不会阻止Action流向Reducer,如果你已经有缓存数据,Effect不会再触发
success/failAction来重置loading,最终就会导致loading状态异常。
解决方案
方案1:修改Reducer逻辑,设loading前先判断缓存是否存在
直接在Reducer处理loadPackingList的逻辑中,先判断当前State里有没有已有的列表,有就不修改loading状态,改动量最小:
export const packingReducer = createReducer( initialState, on(PackingPageActions.loadPackingList, (state) => { // 已有数据的情况下不修改loading状态 if (state.packingList?.length > 0) return state return { ...state, loading: true } }), // 其余success、fail的reducer逻辑保持不变 on(PackingApiActions.loadPackingListSuccess, (state, {list}) => ({ ...state, loading: false, packingList: list })), on(PackingApiActions.loadPackingListFail, (state) => ({ ...state, loading: false })) )
方案2:拆分Action,职责分离更规范
你可以把原来的Action拆成两个,逻辑边界更清晰,后续扩展更方便:
- 组件触发的
PackingPageActions.requestPackingList:仅用于通知Effect判断是否需要加载,Reducer不监听这个Action - 真正触发加载的
PackingPageActions.startLoadingPackingList:Effect判断需要发起请求时分发,Reducer监听这个Action来设置loading为true
修改后的Effect代码:
import { EMPTY, concat } from 'rxjs'; loadPackingList$ = createEffect(() => { return this.actions$.pipe( ofType(PackingPageActions.requestPackingList), switchMap((action) => of(action).pipe( withLatestFrom(this.store.select(selectPackingList)), switchMap(([action, list]) => { // 已有数据直接终止流 if (list?.length > 0) return EMPTY // 先分发开始加载的Action,再发起API请求 return concat( of(PackingPageActions.startLoadingPackingList()), this.packingService.getPackingList(action.request).pipe( map((list) => PackingApiActions.loadPackingListSuccess({ list })), catchError((errors) => of(PackingApiActions.loadPackingListFail({ errors })) ) ) ) }) ) ) ); });
修改后的Reducer代码:
export const packingReducer = createReducer( initialState, // 仅监听startLoading的Action来设置loading on(PackingPageActions.startLoadingPackingList, (state) => ({ ...state, loading: true })), // 其余success、fail逻辑保持不变 )
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

