我在理解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,但它们在效果中的任何位置都没有连接。我真的很想知道这是怎么发生的,但我在任何地方都找不到答案。这是我的商店设置-
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);
效果.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
){}
}
我认为发生这种情况是因为您从getAllUsers
返回一个Observable
,当 Firebase 集合发生变化时会发出一个值。然后返回的Observable
通过mergeMap
与loadUsers$
效应的可观察量在内部链接,当一个新值来自源可观察量(this.adminService.getAllUsers()
)时,该可观察量映射到LoadUsersSuccessAction
操作,然后LoadUsersSuccessAction
被调度。
因此,如果您想更改此行为,则需要在第一个值来自 Firebase 集合时立即完成可观察getAllUsers()
,如下所示:
getAllUsers(): Observable<object> {
console.log('getAllUsers');
return this.afs
.collection('users', (ref: any) => ref.where('role', '!=', 'admin'))
.valueChanges()
.pipe(take(1));
}
或者您需要从效果中提取逻辑(从 firebase 获取valuesChanges
)并在其他地方使用它。