我正在尝试遵循 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)!);
}
);
任何帮助表示赞赏!
给定 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