我正在使用独立组件在 Angular 16 项目中设置 NgRx。我疯狂地尝试在 API 调用后自动更新组件的状态。
我已经定义了行动:
export const SchoolApiActions = createActionGroup({
source: 'Schools API',
events: {
getSchoolPreviews: emptyProps(),
getSchoolPreviewsSuccess: props<{ schoolPreviews: SchoolPreview[] }>(),
getSchoolPreviewsFail: props<{ error: any }>(),
},
});
我设置了一个效果,当调度
getSchoolPreviews
操作时会触发:
loadSchoolPreviews$ = createEffect(() => {
return this.actions$.pipe(
ofType(SchoolApiActions.getSchoolPreviews),
switchMap(() => {
return this.schoolsService.getSchoolPreviews().pipe(
map((schoolPreviews) =>
SchoolApiActions.getSchoolPreviewsSuccess({
schoolPreviews,
})
),
catchError((error) =>
of(SchoolApiActions.getSchoolPreviewsFail({ error }))
)
);
})
);
});
最后,我有一个减速器和一个选择器来修改状态并提供状态切片:
export interface SchoolsState {
schoolPreviews: SchoolPreview[];
loading: boolean;
error: any;
}
export const initialState: SchoolsState = {
schoolPreviews: [],
loading: false,
error: null,
};
export const schoolsReducer = createReducer(
initialState,
// School Previews
on(SchoolApiActions.getSchoolPreviews, (state) => ({
...state,
loading: true,
})),
on(SchoolApiActions.getSchoolPreviewsSuccess, (state, payload) => {
return {
...state,
schoolPreviews: [...payload.schoolPreviews],
loading: false,
};
}),
on(SchoolApiActions.getSchoolPreviewsFail, (state, { error }) => ({
...state,
loading: false,
error,
})),
);
export const getSchoolPreviews = (state: SchoolsState) => state.schoolPreviews;
在组件中,我的
onInit
中进行以下设置:
ngOnInit() {
this.schoolPreviews$ = this.store.select(getSchoolPreviews);
this.store.dispatch(SchoolApiActions.getSchoolPreviews());
}
在我的模板中,我使用异步管道运算符来订阅状态:
<div class="col-4 mt-4">
<select class="form-select" aria-label="School select" (change)="selectSchool($event)">
<option selected [value]="-1">Select a School</option>
<option *ngFor="let schoolPreview of schoolPreviews$ | async" [value]="schoolPreview.id">
{{ schoolPreview.name }}
</option>
</select>
</div>
我已经验证了操作/效果正在被触发,API 调用成功,并且状态已通过 Redux 开发工具更新。
但无论我做什么,我都无法让异步管道显示更新的状态。它会发射一次,然后就不会再发射。我尝试过更改更改检测策略,更改在状态下设置新数组的方式,但没有任何效果。
我错过了一些简单的事情吗?为什么状态变化没有反映出来?
需要订阅选择器,如果您不订阅选择器,它将不会触发。
this.store.pipe(select(getSchoolPreviews)).subscribe((res)=>{ this.schoolPreviews$ = res; });