Как отобразить товары из магазина redux в приложении angular5?
У меня есть компонент 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() ] : []);
}
}
Проблема в том, что я не могу отображать элементы в списке. Вот корневой редуктор:
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;
}
}
Как я могу отобразить элементы? Похоже, что первый элемент добавляется в состояние с помощью приставки. Здесь также githublink
1 ответ
Это выглядит не совсем правильно:
var newstate = state;
newstate.items.push(action.data.data.value);
return newstate;
Вы на самом деле не создаете новый массив или копию: оба newstate
а также state
один и тот же массив, так что вам, вероятно, лучше вернуть новый массив с мелким клонированием:
export function rootReducer(state: AppState, action): AppState {
switch (action.type) {
case TodoActions.ADD:
return {
...state,
items: [
...state.items,
action.data.value
]
}
default:
return state;
}
}
Вы можете заметить, что я отключил спецификатор типа action
, Я не уверен, что имеет смысл указать Action
как тип для действия, в большинстве примеров кода, которые я видел, он прошел нетипизированный так:
export function rootReducer(state: AppState, action): AppState {
Это позволит избежать жалоб TS на отсутствие data
по типу Action
, Кроме того, вы можете определить тип настраиваемого действия для каждого написанного вами редуктора.
Как только вы пройдете через это, я думаю, что вы не видите никаких элементов, потому что вы называете массив 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
,