我想在一个简单的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-browser.js:2628) 在ZoneDelegate.invokeTask(zone.js:421) at Object.onInvokeTask(core.js:4740)
如果我在调试器中检查它,this.ngRedux.getState()
为undefined
,则它找不到todos
属性。所以似乎初始化出错了,但我不明白为什么。
任何想法我做错了什么?
答案 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;
}
}
因为最初没有调度任何动作,因此必须返回初始状态。