问题描述
我有一个场景,我想在使用 NGRX 加载组件时显示一些数组(例如:文件列表)。
所以我所做的是创建了如下两个动作
-
GET_FILES => GetFiles 作为类
-
SET_FILES => 将文件设置为类
和一个维持状态的减速器
export interface State {
files: Files[];
}
const initialState: State = {
files: []
};
export function filesReducer(
state: State = initialState,action: FilesAction.FilesAction
) {
switch (action.type) {
case FilesAction.GET_FILES:
return {
...state
};
case FilesAction.SET_FILES:
const files: Files[] = action.payload;
return {
...state,...files
};
default:
return state;
}
}
然后就会有一个 effect 调用 rest api 来获取文件列表,然后 effect 将调度 SET_FILES 操作。
@Effect()
getFiles = this.action$.pipe(
ofType(FilesAction.GET_FILES),switchMap(() => {
return this.http.get<Files[]>(environment.baseURI + 'api/get-files');
}),map(filesstate => {
return new FilesAction.SetFiles(filesstate);
})
);
当组件在 ngOnInit 上加载时,我们可以分派 SET_FILES 的一个动作,它反过来执行一个效果,然后负责分派另一个 SET_FILES 的动作。
export class FileListComponent implements OnInit {
iFileId: number = 0;
fileList: Files[] = [];
constructor(private store: Store<fromApp.AppState>) {
//Problem Area
this.store.select('files').subscribe(files => {
this.fileList = files.files;
console.log('FileList:');
console.log(this.fileList);
});
}
ngOnInit(): void {
this.store.dispatch(new FilesActions.GetFiles(this.iFileId));
}
}
在这里,问题是我能够成功地在 ngOnInit 上调度操作,如果我在 console.log 上执行操作,那么我将获得文件列表,但是我如何将它存储在一个变量中,就像我在构造函数中尝试做的那样?
>解决方法
在你的组件 ts 中存储一个对选择器结果的引用在一个 observable 中:
export class FileListComponent implements OnInit {
iFileId: number = 0;
fileList$ = this.store.select('files'); // <<<-- add this
constructor(private store: Store<fromApp.AppState>) {}
ngOnInit(): void {
this.store.dispatch(new FilesActions.GetFiles(this.iFileId));
}
}
在您的模板中:
<p *ngIf="fileList$ | async as fileList" *ngFor="let file of fileList.files">
{{ file }}
</p>
注意订阅并检查发出的值是否为真的 ngIf.. as
语法 - 然后您可以安全地在 fileList
中使用 ngFor
。
其他建议
-
您的减速器中不需要
FilesAction.GET_FILES
大小写,因为它不会改变状态。 -
以触发它们的相关事件命名您的减速器(参见 https://2018.ng-conf.org/sessions/good-action-hygiene-ngrx/ 4:30):
GET_FILES => FILES_REQUESTED
SET_FILES => FILES_LOADED