NgRxReducer - 更改数组中特定对象的状态

问题描述 投票:0回答:1

我正在尝试遵循 NgRx 演练,但将其调整为比添加或删除书籍更复杂的东西。

NgRx 演练

我想要一个大学对象数组,并且能够通过 ID 找到一所大学,然后更改它的总学生数。

我快到了。完全被减速机卡住了。

模型/univeristy.model.ts:

export interface University {

    id: string | undefined;
    name: string | undefined;
    total_students: number | undefined;
}

行动/university.actions.ts:

import { createActionGroup, props } from '@ngrx/store';
import { University } from '@models/university';

export const UniversityActions = createActionGroup({
  source: 'University',
  events: {
    'Change Student Total': props<{ universityId: string, total_students: number }>(),
  },
});

export const UniversityApiActions = createActionGroup({
  source: 'University API',
  events: {
    'Retrieved Universities': props<{ universities: Array<University> }>(),
  },
});

动作/动作类型.ts:

import * as ActionTypes from './university.actions';

    export {ActionTypes};

我在这里迷路了...

Reducers/collection.reducer.ts:

import { createReducer, on } from '@ngrx/store';
import { UniversityActions } from '@actions/actions/university.actions';

export const initialState: Array<string> = [];


export const collectionReducer = createReducer(
  initialState,
  on(UniversityActions.changeStudentTotal, (state, { universityId, total }) => {
    
    // How to modify the state to change the total of a specific univeristy in the list?
    // Find the univeristy by universityId then create a new record for it with the new total?
    ...state,
    universities: { ...state.universities, universities: {id: universityId, total: total} },

  })

);

Reducers/university.reducer.ts:

import { createReducer, on } from '@ngrx/store';
import { ActionTypes } from '@state/actions/action-types';
import { University } from '@models/university.model';

export interface UniversityState {
  universities: University[];
  status: 'start' | 'loading' | 'error' | 'success';
  error: string;
}

// The starting global values
export const initialState: Array<University> = [];

export const universityReducer = createReducer(
  initialState,
  on(
    ActionTypes.UniversityApiActions.retrievedUniversities,
    (_state, { universities }) => universities
  )
);

选择器/university.selectors.ts:

import { createSelector, createFeatureSelector } from '@ngrx/store';
import { University } from '@models/university.model';

export const selectUniversity = createFeatureSelector<Array<University>>('universities');

export const selectUniversityState =
  createFeatureSelector<Array<string>>('collection');

export const selectUniversities = createSelector(
  selectUniversity,
  selectUniversityState,
  (universities, collection) => {
    return collection.map((id) => universities.find((university) => university.id === id)!);
  }
);

任何帮助表示赞赏!

angular ngrx ngrx-store
1个回答
0
投票

给定 ID,您需要搜索大学并替换其数据,而不改变商店内容。你可以像下面这样做:

on({...}),
on(UniversityActions.changeStudentTotal, (state, {universityId, total}) => {
  const universityCopy = [...state.universities]; // create a copy of the original, 
  const index = universityCopy.findIndex(university => university.id === univertisyId);
  // you should add a validation if "index" is -1 if it doesn't find any
  const searchedUniversity = {...universityCopy[index]} as University;
  
  // Modify the copy as you need
  searchedUniversity.total_students = total;
  universityCopy[index] = {...searchUniversity} as University;
  state.universities = [...universityCopy]; // give back to "universities" a 'new' array
  return { ...state };
}),
on({...})

既然你使用的是

NgRx
,你也可以使用
NgRx Entity
进行CRUD操作
(Create, Retrieve, Update, Delete)
,而不是传入
university id
,你应该传入大学
object

on(UniversityActions.changeStudentTotal, (state, {theModifiedUniversityObject}) => 
 ({...state, universities: adapter.updateOne(theModifiedUniversityObject, state.universities)}))

还有可用的操作,例如:

  • updateMany
  • upsertOne
    (添加或更新)
  • upsertMany
  • addOne
  • deleteOne
  • 还有更多...

有关

NgRx Entity
的更多信息可以阅读官方docs

© www.soinside.com 2019 - 2024. All rights reserved.