加载组件时如何使用 NGRX 检索数据(如文件列表数组)

How to retrieve data (like an array of file list) using NGRX when component is loaded

我有一个场景,我想在使用 NGRX 加载组件时显示一些数组(例如:文件列表)。

所以我所做的是创建如下两个动作

  1. GET_FILES => GetFiles as class

  2. SET_FILES => 将文件设置为 class

和一个维护状态的减速器

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 获取休息 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 将对选择器结果的引用存储在一个可观察对象中:

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 语法来订阅并检查发出的值是否真实 - 然后您可以安全地在 ngFor.

中使用 fileList

其他推荐

  1. 你的 reducer 不需要 FilesAction.GET_FILES case,因为它不会改变状态。

  2. 在触发它们的相关事件之后命名你的减速器(参见 https://2018.ng-conf.org/sessions/good-action-hygiene-ngrx/ 4:30):

   GET_FILES => FILES_REQUESTED  
   SET_FILES => FILES_LOADED