我一直在一个虚拟的“Todo”项目中尝试使用@ ngrx/entity,该项目具有单个AppModule,单个reducer和单个组件。但是,我在尝试时遇到了问题。
我的 Action 很简单,只是一些CRUD操作:
import { Action } from '@ngrx/store';
import { Todo } from '../../models/todo';
export const CREATE = '[Todo] Create'
export const UPDATE = '[Todo] Update'
export const DELETE = '[Todo] Delete'
export class Create implements Action {
readonly type = CREATE;
constructor(public todo: Todo) { }
}
export class Update implements Action {
readonly type = UPDATE;
constructor(
public id: string,
public changes: Partial<Todo>,
) { }
}
export class Delete implements Action {
readonly type = DELETE;
constructor(public id: string) { }
}
export type TodoActions
= Create
| Update
| Delete;
然后,我的reducer文件包含处理实体所需的所有内容:
import * as actions from './todo.actions';
import { EntityState, createEntityAdapter } from '@ngrx/entity';
import { createFeatureSelector } from '@ngrx/store';
import { Todo } from '../../models/todo';
export interface TodosState extends EntityState<Todo> {}
export const todoAdapter = createEntityAdapter<Todo>();
export const initialState: TodosState = todoAdapter.getInitialState();
export function todoReducer(state: TodosState = initialState, action: actions.TodoActions) {
console.log("Got new action", action);
switch(action.type) {
case actions.CREATE:
return todoAdapter.addOne(action.todo, state);
case actions.UPDATE:
return todoAdapter.updateOne({
id: action.id,
changes: action.changes
}, state);
case actions.DELETE:
return todoAdapter.removeOne(action.id, state);
default:
return state;
}
}
export const {
selectIds,
selectEntities,
selectAll,
selectTotal
} = todoAdapter.getSelectors();
在我的
app.module.ts
文件中,我正在执行以下操作:import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { AppComponent } from './app.component';
import { todoReducer } from './reducers/todo.reducer';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
StoreModule.forRoot({
todo: todoReducer
}),
StoreDevtoolsModule.instrument({maxAge: 25}),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
最后,在我的
app.component.ts
中,我只是尝试创建两个TODO:import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import * as fromTodo from './reducers/todo.reducer';
import { Todo } from '../models/todo';
import { Create } from './reducers/todo.actions';
@Component({
selector: 'app-root',
template: `
`,
styles: []
})
export class AppComponent implements OnInit {
public todos: Observable<Todo[]>;
constructor(private store: Store<fromTodo.TodosState>) {
this.store.dispatch(new Create({
title: "Test todo",
content: "This is a test todo",
date: new Date()
}))
this.store.dispatch(new Create({
title: "Test todo 2",
content: "This is another todo",
date: new Date()
}))
}
ngOnInit() {
this.todos = this.store.select(fromTodo.selectAll);
}
}
但是,运行此命令后,我检查了
Redux DevTools
。我看到它仅创建第一个TODO,其ID为“未定义”。我的reducer中的
console.log
显示@ngrx/store/init
,以及[TODO]
创建 Action 此外,如果我尝试通过组件中的
ngFor | async
进行todos
编码,则会收到各种错误,具体取决于我尝试执行的操作(主要是“无法读取未定义的'map'属性”)。 最佳答案
经过研究后,我注意到@ngrx/entity
使用了所使用模型的id
属性。
就我而言,我的Todo
模型没有任何id
属性,因此@ngrx/entity
无法处理我的实体。
我以为它是在内部生成ID的,但显然不是。
因此,解决此问题的方法是在模型中添加id
属性,并在每次向状态添加项目时自动生成。
例如,有一个Angular2 UUID模块。
就我而言,我将ngrx
与AngularFire2
一起使用,后者具有createId()
方法:const id = this.afs.createId()
。然后,可以将其添加到要添加的项目中,然后将其存储在Firestore数据库中。
关于javascript - NgRX实体: ids are undefined in the State,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48995046/