redux 从Angular中的NgRx减速器访问数据时出现问题

kxeu7u2r  于 2022-11-12  发布在  Angular
关注(0)|答案(1)|浏览(162)

我有个问题。
我使用NgRx来处理应用程序的状态,因此我创建了几个reducer,其中包含管理员用户、管理这些用户的公司、这些公司的调查类型等。
所以我有一个还原器为每一个,我试图创建几个StoreModule.forFeature,但我注意到,我有一个错误一样,它总是试图访问“管理员用户”的featureKey,即使它指示另一个featureKey(例如,companyStateFeatureKey...),我正在阅读,根据我的理解,这是为reducers,他们必须与ActionReducerMapMap,所以我这样做了,它将数据保存在存储中,但我不知道如何访问它,因为它创建了几个嵌套的“admins”属性,如果我使用“admin.admins”,它会因为数据模型而给我一个错误,所以我想知道是否有一种方法可以创建几个featureReducer,或者如何访问具有许多嵌套的数据。
下面是部分代码:
admin.actions.ts

import { createAction, props } from '@ngrx/store';
import { Admin } from "../../components/models";

export const GET_ADMIN = createAction('[ADMIN PAGE] Init');

export const GET_ADMINS_SUCCESS = createAction(
  '[ADMIN PAGE] Admins Success',
  props<{ admins: Admin[] }>()
);

export const GET_ADMINS_ERROR = createAction(
  '[ADMIN PAGE] Admins Error',
  props<{ error: string }>()
);

admin.effects.ts

import { Injectable } from "@angular/core";
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { catchError, map, of, exhaustMap } from 'rxjs';
import { AdminService } from '../../services/admin.service';
import { GET_ADMIN, GET_ADMINS_ERROR, GET_ADMINS_SUCCESS } from '../actions/admin.actions';

@Injectable()
export class AdminsEffect {
  constructor(
    private actions$: Actions,
    private adminService: AdminService,
  ) {}

  loadAllAdmins$ = createEffect(() =>
    this.actions$.pipe(
      ofType(GET_ADMIN),
      exhaustMap((initAction) => {
        return this.adminService.getAllAdmins().pipe(
          map(admins => GET_ADMINS_SUCCESS({admins})),
          catchError(() => of(GET_ADMINS_ERROR({error: "There was an error getting the admins"}))),
        );
      })
    )
  )
};

admin.reducers.ts

import { Action, createReducer, on } from "@ngrx/store";
import { Admin } from "../../components/models/Admin";
import { GET_ADMINS_SUCCESS } from "../actions/admin.actions";

export interface AdminState {
  admins: Admin[];
}

const initialAdminState: AdminState = {
  admins: [],
};

export const adminReducer = createReducer(
    initialAdminState,
    on(GET_ADMINS_SUCCESS, (state, {admins}) => ({
      ...state,
      admins,
    }))
);

admin.selectors.ts

import { createFeatureSelector, createSelector } from '@ngrx/store';
import { adminFeatureKey } from '../admin.state';
import { AdminState } from '../reducers/admin.reducers';

export const selectAdmins = createFeatureSelector<AdminState>(adminFeatureKey);

export const admins = createSelector(
  selectAdmins,
  (selectAdmins) => selectAdmins.admins
)

admin.state.ts

import { ActionReducerMap } from '@ngrx/store';
import { AdminState, adminReducer } from './reducers/admin.reducers';

export interface AdminFlowState {
  admins: AdminState;
}

export const reducers: ActionReducerMap <AdminFlowState> = {
  admins: adminReducer
}

export const adminFeatureKey = "adminState"

admin.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { CreateAdmin } from '../components/interfaces/CreateAdmin';
import { Admin } from "../components/models/Admin";
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AdminService {

  serverURL = environment.serverURL;

  constructor(private http: HttpClient) { }

  getAllAdmins(): Observable<Admin[]> {
    return this.http.get<Admin[]>(`${this.serverURL}/admins`)
  }
  ...
}

Admin.ts

export interface Admin {
  code: string;
  name: string;
  fsbs: boolean;
  createdIp: string;
  createdAt: Date;
  updatedIp: string;
  updatedAt: Date;
  logo?: Blob;
  pwd?: string;
}

admin.module.ts

...
imports: [
    CommonModule,
    MaterialModule,
    NgxChartsModule,
    AdminRoutingModule,
    StoreModule.forFeature(adminFeatureKey, reducers),
    EffectsModule.forFeature([AdminsEffect]),
    ReactiveFormsModule,
    FormsModule
  ],
...

admins-table.component.ts

import { Component, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { Admin } from "../models/Admin";
import { select, Store } from '@ngrx/store';
import { admins } from '../../store/selectors/admin.selectors';
import { GET_ADMIN } from '../../store/actions/admin.actions';

@Component({
  selector: 'app-admins-table',
  templateUrl: '../views/admins-table.component.html',
  styleUrls: ['../styles/admins-table.component.scss']
})
export class AdminsTableComponent {
  columnas: string[] = ['code', 'name', 'fsbs', 'createdIp', 'createdAt', 'updatedIp', 'updatedAt', 'logo', 'edit'];
  admins: Admin[] = [];
  dataSource: any;

  @ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort!: MatSort;

  constructor(private store: Store) {}

  ngOnInit() {
    this.store.pipe(select(admins))
    .subscribe(admin => {
      console.log(admin);
      this.store.dispatch(GET_ADMIN());
      this.admins = admin;
      this.dataSource = new MatTableDataSource<Admin>(this.admins);
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    });
  }

  filter(event: Event) {
    const filtro = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filtro.trim().toLowerCase();
  }
}

管理员订阅的控制台日志:

{admins: [
   ...
   {
    "code": "002",
    "name": "Manuel",
    "pwd": "...",
    "fsbs": false,
    "createdIp": "157.100.75.247",
    "createdAt": "2022-09-07T23:08:08.310Z",
    "updatedIp": "157.100.75.247",
    "updatedAt": "2022-09-07T23:08:08.310Z",
    "logo": "..."
   },
  ...
 ]
}
mwecs4sa

mwecs4sa1#

我已经得到了解决方案,我在文档中得到了它,我在减速器中缺少了这个:

...
export function reducer(state: AdminState | undefined, action: Action) {
   return adminReducer(state, action);
}
...

在那之后,我能够创建我需要的所有StoreModule.forFeature(),而不需要使用ActionReducerMap并删除admin.state.ts中的所有内容。

相关问题