数据更新后,NgRx 如何更新远程数据?

How NgRx updates remote data when the data has been updated?

我无法理解 NgRx 的工作原理。我有一个用户列表,它是通过 Firebase 商店的服务加载的,如下所示:

   getAllUsers():Observable<object>{
    console.log('getAllUsers');
    return this.afs.collection('users', (ref:any) => ref.where("role", '!=', 'admin')).valueChanges();
  }

然后我在存储用户列表的模块中有一个商店设置,它工作得很好并且在管理员登录到应用程序时加载用户列表一次,因为它是在仪表板中调度的容器管理路由器插座。其中一部分是管理员可以单击每个用户并更新他们的信息,从而从未连接到商店的服务中触发此功能:

 async updateUserData(data:any, id:any){
    await this.afs.collection('users').doc(id).update(data); 
  } 

我原以为当用户数据更新时,存储的用户列表在再次下载之前不会更新,但它会相应地更新。 这是怎么回事?我正在记录 getAllUsers 函数,但它没有被再次调用。取而代之的是操作:LoadUsersSuccess 在调用 updateUserData 时被调用,但它们在效果中的任何地方都没有连接。我真的很想知道这是怎么回事,但我在任何地方都找不到答案。这是我的商店设置-

actions.ts:

import { Action } from "@ngrx/store";

export enum AdminActionTypes{
    LOAD_USERS = '[ADMIN] Load Users',
    LOAD_USERS_SUCCESS = '[ADMIN] Load Users Success',
    LOAD_USERS_FAILURE = '[ADMIN] Load Users Failure',
}

export class LoadUsersAction implements Action {
    readonly type = AdminActionTypes.LOAD_USERS;
}
export class LoadUsersSuccessAction implements Action {
    readonly type = AdminActionTypes.LOAD_USERS_SUCCESS;
    constructor(public payload: any){}
}
export class LoadUsersFailureAction implements Action {
    readonly type = AdminActionTypes.LOAD_USERS_FAILURE;
    constructor(public payload: Error){}
}

export type AdminAction = LoadUsersAction | LoadUsersFailureAction | LoadUsersSuccessAction;

reducer.ts:

import { AdminActionTypes, AdminAction} from './admin.actions';
import { createFeature, createFeatureSelector, createSelector } from '@ngrx/store';
export interface AdminState {
    list: any[],
    loading: boolean,
    error: Error
}

const initialState: AdminState = {
    list:[],
    loading:false,
    error: {name: "", message: ""}
}

export function AdminReducer(
    state: AdminState = initialState,
    action: AdminAction,
){
    switch (action.type){
        case AdminActionTypes.LOAD_USERS:
            return {...state,  loading: true};
        case AdminActionTypes.LOAD_USERS_SUCCESS:
            return {...state, list:action.payload, loading:false};
        case AdminActionTypes.LOAD_USERS_FAILURE:
            return {...state, error:action.payload, loading:false};
        default:
            return state;
    }
}
export const getAdminState = createFeatureSelector<AdminState>('admin');

export const loadUsers = createSelector(getAdminState, (state: AdminState) => state.loading);
export const loadUsersSuccess = createSelector(getAdminState, (state: AdminState) => state.list);
export const loadUsersFailure = createSelector(getAdminState, (state: AdminState) => state.error);

effects.ts:


    @Injectable()
export class AdminEffects {
    loadUsers$ = createEffect(
        () => this.actions$
        .pipe(
            ofType<LoadUsersAction>(AdminActionTypes.LOAD_USERS), 
            mergeMap(
                () => this.adminService.getAllUsers()
                .pipe(
                    map(data => new LoadUsersSuccessAction(data)),
                    catchError(error => of (new LoadUsersFailureAction(error)))
                ),
            ),
        ),
    )
    constructor(
        private actions$: Actions, 
        private adminService: AdminService
        ){}
}

我认为发生这种情况是因为您 return 来自 getAllUsersObservable 会在 Firebase 集合发生变化时发出一个值。然后 returned Observable 通过 mergeMaploadUsers$ 效果的 Observable 内部链接,当新值到来时映射到 LoadUsersSuccessAction 动作来自源 Observable (this.adminService.getAllUsers()),然后 LoadUsersSuccessAction 被调度。

所以如果你想改变这个行为,你需要在第一个值来自 Firebase 集合时立即完成 getAllUsers() observable,如下所示:

getAllUsers(): Observable<object> {
  console.log('getAllUsers');
  return this.afs
    .collection('users', (ref: any) => ref.where('role', '!=', 'admin'))
    .valueChanges()
    .pipe(take(1));
}

或者您需要从效果中提取逻辑(从 firebase 获取 valuesChanges)并在其他地方使用它。