Redux / Angular getState()未定义

时间:2018-03-09 11:23:01

标签: angular redux

我想在一个简单的Angular应用程序中实现Redux。作为一个试用版,我想制作一个简单的待办事项列表,但我很难让它发挥作用。

以下是示例代码:

应用-module.ts

import { NgRedux, NgReduxModule } from '@angular-redux/store';
import { IAppState, rootReducer, INITIAL_STATE } from './store';
import { TodoListComponent } from './todo-list/todo-list.component';

@NgModule({
  declarations: [
    AppComponent,
    TodoListComponent
  ],
  imports: [
    ...
    NgReduxModule
  ],
...   
})

export class AppModule {
  constructor(ngRedux: NgRedux<IAppState>) {
    ngRedux.configureStore(rootReducer, INITIAL_STATE);
  }
}

store.ts

import { ADD_TODO } from './actions';
import { tassign } from 'tassign';

export interface IAppState {
  lastUpdate: Date;
  todos: Todo[]; 
  // I tried `any[]`, but it didn't help.
}

export const INITIAL_STATE: IAppState = {
  lastUpdate: null,
  todos: [] 

//尝试了todos:new Array(),但没有什么区别     };

export function rootReducer(state: IAppState, action): IAppState {
    switch (action.type) {
    case ADD_TODO:
        return tassign(state, {
            todos: state.todos.concat(action.todo),
            lastUpdate: new Date()
        });
    }
    return state;
}

todo.ts

export class Todo {
  title: string;
}

待办事项列表-component.html

<h1>Todo List</h1>
<input type="text" #title>
<button (click)="addTodo(title)">Add</button>
<ul>
  <li *ngFor="let todo of todos | async">
    <span>{{ todo.title }}</span>
  </li>
</ul>

待办事项列表-component.ts

import { Component } from '@angular/core';
import { NgRedux, select } from '@angular-redux/store';
import { IAppState } from '../store';
import { ADD_TODO } from '../actions';
import { Todo } from '../todo';

export class TodoListComponent {
  @select((s: IAppState) => s.todos) todos: Todo[];

  constructor(private ngRedux: NgRedux<IAppState>) {
    ngRedux.subscribe(() => console.log(ngRedux.getState()));
  }

  addTodo(input) {
    if (!input.value) {
      return;
    }

    const todo = new Todo();
    todo.title = input.value;
    this.ngRedux.dispatch({
      type: ADD_TODO,
      todo: todo
    });

    input.value = '';
  }
}

package.json

{
  "name": "angular-demo",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular-redux/store": "^7.1.1",
    "@angular/animations": "^5.2.7",
    "@angular/cdk": "^5.2.3",
    "@angular/common": "^5.2.4",
    "@angular/compiler": "^5.2.4",
    "@angular/core": "^5.2.4",
    "@angular/forms": "^5.2.4",
    "@angular/http": "^5.2.4",
    "@angular/material": "^5.2.3",
    "@angular/platform-browser": "^5.2.4",
    "@angular/platform-browser-dynamic": "^5.2.4",
    "@angular/router": "^5.2.4",
    "core-js": "^2.4.1",
    "font-awesome": "^4.7.0",
    "hammerjs": "^2.0.8",
    "immutable": "^3.8.2",
    "redux": "^3.7.2",
    "rxjs": "^5.1.0",
    "tassign": "^1.0.0",
    "typescript": "^2.7.2",
    "web-animations-js": "^2.3.1",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/cli": "1.7.3",
    "@angular/compiler-cli": "^5.2.4",
    "@angular/language-service": "^5.2.4",
    "@types/jasmine": "2.8.6",
    "@types/node": "~9.4.6",
    "codelyzer": "~4.2.1",
    "jasmine-core": "~3.1.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-cli": "~1.0.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "protractor": "~5.3.0",
    "ts-node": "~5.0.0",
    "tslint": "~5.9.1",
    "typescript": "~2.7.2"
  }
}

因此,当我输入一些文字并点击Add时,我希望将其添加到todos列表并显示在文本框下方。

但相反,我在控制台上遇到了一个js错误,说:

  

错误TypeError:无法读取未定义的属性'todos'       at TodoListComponent.addTodo(todo-list.component.ts:25)       在Object.eval [as handleEvent](TodoListComponent.html:4)       at handleEvent(core.js:13547)       at callWithDebugContext(core.js:15056)       at Object.debugHandleEvent [as handleEvent](core.js:14643)       at dispatchEvent(core.js:9962)       在eval(core.js:10587)       在HTMLButtonElement.eval(platform-b​​rowser.js:2628)       在ZoneDelegate.invokeTask(zone.js:421)       at Object.onInvokeTask(core.js:4740)

如果我在调试器中检查它,this.ngRedux.getState()undefined,则它找不到todos属性。所以似乎初始化出错了,但我不明白为什么。

任何想法我做错了什么?

1 个答案:

答案 0 :(得分:2)

您正在丢失减速器功能中的默认返回值

export function rootReducer(state: IAppState = INITIAL_STATE, action): IAppState {
    switch (action.type) {
    case ADD_TODO:
        return tassign(state, {
            todos: state.todos.concat(action.todo),
            lastUpdate: new Date()
        });

     default: return state;
    }
}

因为最初没有调度任何动作,因此必须返回初始状态。