1

我有一个 angular5 组件,我正在尝试与 reduxstore 连接,它看起来像这样:

import { Component } from '@angular/core';
import { NgRedux, select, DevToolsExtension } from '@angular-redux/store';
import { TodoActions } from './actions';
import { AppState, INITIAL_STATE, rootReducer } from './store';
import {Observable} from "rxjs/Observable";

@Component({
  selector: 'app-root',
  template: `    
    <input type="text" #edit />
    <button (click)="actions.add({data:edit,action:'ADD'})">add</button>
    <p>The list is:</p>
    <ul>
      <li *ngFor="let item of (items | async)">
        {{item}}
      </li>
    </ul>
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  @select() readonly items$: Observable<string[]>;

  constructor(
    ngRedux: NgRedux<AppState>,
    devTools: DevToolsExtension,
    private actions: TodoActions) {

    ngRedux.configureStore(
      rootReducer,
      INITIAL_STATE,
      null,
      devTools.isEnabled() ? [ devTools.enhancer() ] : []);
  }
}

问题是我无法在列表中显示项目。这是rootreducer:

import {Action} from 'redux';
import {TodoActions} from './actions';

export interface AppState {
  items: string[];
}
export const INITIAL_STATE: AppState = {items: []};

export function rootReducer(state: AppState, action: Action): AppState {
  switch (action.type) {
    case TodoActions.ADD:
      var newstate = state;
      newstate.items.push(action.data.data.value);
      return newstate;
  }
  ;

default:
  return state;
}
}

如何显示项目?看起来第一项是从 redux 控制台添加到状态的。这里也是一个github链接

4

1 回答 1

1

这看起来不太正确:

  var newstate = state;
  newstate.items.push(action.data.data.value);
  return newstate;

您实际上并没有创建新数组或副本:两者newstatestate都是同一个数组,因此您最好返回一个浅克隆的新数组:

export function rootReducer(state: AppState, action): AppState {
  switch (action.type) {
    case TodoActions.ADD:
      return {
        ...state,
        items: [
          ...state.items,
          action.data.value
        ]
      }

    default:
      return state;
  }
}

您可能会注意到我已经取消了类型说明符 off action。我不确定将其指定Action为操作类型是否有意义,在我见过的大多数示例代码中,这些代码都是无类型传递的:

export function rootReducer(state: AppState, action): AppState {

这将避免 TS 抱怨缺少dataon type Action。或者,您可以为您编写的每个 reducer 定义自定义操作类型。

一旦你过去了,我认为你没有看到任何项目的原因是因为你items$@select装饰器中命名了数组。所以:

@Component({
  selector: 'app-root',
  template: `    
    <input type="text" #edit />
    <button (click)="actions.add({value:edit.value,action:'ADD'})">add</button>
    <p>The list is:</p>
    <ul>
      <li *ngFor="let item of (items$ | async)">
        {{item}}
      </li>
    </ul>
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  @select() readonly items$: Observable<string[]>;

效果更好。请注意,我稍微调整了按钮定义以避免传递整个输入,因为您只需要value.

于 2017-12-09T09:51:48.663 回答