ngrx 从效果更新状态

时间:2021-01-14 03:58:04

标签: angular typescript ngrx interceptor ngrx-effects

我有 ngrx 存储设置,用于存储当前活动的用户和用户的语言环境。根据用户区域设置,我的拦截器将在所有 API 调用中注入 X-LOCALE 标头。当调用选择用户的操作时,我首先调用单独的 API 来获取该用户的语言环境,将该语言环境传递给拦截器,然后继续调用其余的 API(此时应注入 X-LOCALE 标头)。问题:如何从 user-effects.ts 触发状态更改?

user-reducer.ts

export interface UsersState extends EntityState<UserInfo> {
  loading: boolean;
  currentUser: UserInfo;
  locale: string;
}
const usersReducer = createReducer(
  INITIAL_STATE,
  on(actions.fetchUser, 
  ...bunch of other actions...,
  (state) => ({ ...state, loading: true })
);

user-actions.ts

...bunch of actions
export const fetchUser = createAction('[USERS] Fetch User Request', props<{ uuid: string }>());

user-effects.ts

@Injectable()
export class UsersEffects {
  fetchUser$ = createEffect(() =>
    this.actions$.pipe(
      ofType(usersActions.fetchUser),
      switchMap(({ uuid }) => {
        // here we would read user locale
        return this.usersService.fetchUserLocale(uuid).pipe(
          map((locale) => {
            // ******* here i need to update locale in the state ********
            return uuid;
          });
        }),
      );
    }),
    switchMap((uuid) => {
      // all calls from here on should have "X-LOCALE" header injected
      return forkJoin([
        this.usersService.fetchUser(uuid),
        this.usersService.fetchUserCards(uuid),
        this.usersService.fetchUserPermissions(uuid),
      ]).pipe(
        map(([userDto, cards, permissions]) => {
          const userInfo = { ...userDto, cards, permissions };
          return usersActions.fetchUserSuccess({ userInfo });
        }),
        catchError((error) => of(usersActions.fetchUserFailure({ error }))),
      );
    }),
  ),
);

这里 locale.interceptor.ts 会注入头文件

@Injectable()
  export class HttpHeadersInterceptor implements HttpInterceptor {
    constructor(private store$: Store<UsersState>) {
      this.store$.pipe(select((state) => state.locale)).subscribe((locale: string) => {
        this.locale = locale;
      });
    }
    private locale: string;

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      const defaultHeaders = { Accept: 'application/json, text/plain' };

      if (this.locale) {
        defaultHeaders['X-LOCALE'] = this.locale;
      }

      const authReq = req.clone({ setHeaders: defaultHeaders });

      return next.handle(authReq);
    }
  }

1 个答案:

答案 0 :(得分:1)

好吧,我不确定这是否是最佳实践,但您仍然可以从 switchMap 内调度操作,直接从 map 或您可以将其更改为 {{1 }} 因为没有实际的映射,所以它只是一个副作用。像这样的东西。

tap

正如我所说,我不确定这是否是最佳实践,但在我的项目中,我曾多次使用类似的方法。

相关问题