web-dev-qa-db-ja.com

NgRXエンティティ:IDは州で定義されていません

私は、単一のAppModule、単一のリデューサー、および単一のコンポーネントを使用して、ダミーの "Todo"プロジェクトで@ ngrx/entityを試しました。しかし、私はそれを試すことに問題があります。

私の行動は非常に単純で、いくつかの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;

次に、私のレデューサーファイルには、エンティティを処理するために必要なすべてが含まれています。

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、2つの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は「未定義」であることがわかりました。

App state after running the app and dispatching both events

ぼくの console.log私の減速機の表示@ngrx/store/init、および両方[TODO]アクションを作成

また、ngFor | async自分のコンポーネントのtodosを介して、試行した内容に応じてさまざまなエラーが発生します(主に、「未定義の「マップ」プロパティを読み取れません」)。

9
Thibault Henry

調査の結果、_@ngrx/entity_は使用するモデルのidプロパティを使用していることに気付きました。私の場合、Todoモデルにはidプロパティがなかったため、_@ngrx/entity_はエンティティを処理できませんでした。内部でIDが生成されると思いましたが、そうではないようです。

したがって、この問題の修正は、idプロパティをモデルに追加し、状態に項目を追加するたびに自動生成することです。

たとえば Angular2 UUID モジュールがあります。

私の場合、ngrxと_AngularFire2_を使用していますが、createId()メソッド:const id = this.afs.createId()があります。次に、追加するアイテムに追加して、Firestoreデータベースに保存します。

6
Thibault Henry