Подписка на магазин не вызывается с помощью ngrx store 4

В моем приложении angular (4) я хочу представить редуктор / управление состоянием с помощью ngrx 4.

У меня есть основной модуль

@NgModule({
    imports: [
        // ...
        StoreModule.forRoot({}),
        EffectsModule.forRoot([])
    ],

    declarations: [
        AppComponent
    ],

    bootstrap: [AppComponent]
})

и ленивый загружаемый модуль с

@NgModule({
    imports: [
        StoreModule.forFeature('lazy', {
            items: itemsReducer
        }),
        EffectsModule.forFeature([ItemEffects])
    ],

    declarations: [
        // Components & Directives
    ]
})

это мой редуктор

export function itemsReducer(state: Item[] = [], action: ItemAction<any>) {
    switch (action.type) {

        case ADD:
            return [action.payload, ...state];

        case DELETE:
            return state.filter((item) => item.id !== action.payload.id);

        case ITEMS_LOADED:
            return Object.assign([], action.payload);

        case LOAD_ITEMS:
            return state;

        default:
            return state;
    }
}

Я также имею дело с такими эффектами:

@Injectable()
export class ItemEffects {

    @Effect() addItem$: Observable<Action> = this.actions$.ofType(ADD)
        .mergeMap((payload: any) =>
            this.dataService.addItem(payload)
                // If successful, dispatch success action with result
                .map((data: any) => {
                    return createLoadItemsAction();
                })
                // If request fails, dispatch failed action
                .catch(() => of({ type: 'FAILED' }))
        );

    @Effect() loadItems$: Observable<Action> = this.actions$.ofType(LOAD_ITEMS)
        .mergeMap(() =>
            this.dataService.getAllItems()
                // If successful, dispatch success action with result
                .map((data: Item[]) => (createItemsLoadedAction(data)))
                // If request fails, dispatch failed action
                .catch(() => of({ type: 'FAILED' }))
        );

    constructor(
        private dataService: DataService,
        private actions$: Actions
    ) { }
}

и в моем компоненте с отслеживанием состояния я подписываюсь на этот магазин следующим образом

export class MainItemsComponent implements OnInit {
    items: Observable<Items[]>;

    constructor(private store: Store<any>) {
        this.items = this.store.select('items');
    }

    ngOnInit() {
        this.store.dispatch(createLoadItemsAction());
    }

    // ...

}

С console.logs я вижу, что эффекты работают, редуктор вызывается с правильными действиями «ITEMS_LOADED», все элементы находятся внутри, но они не передаются моему компоненту с отслеживанием состояния и не отображаются.

Мои действия выглядят так

import { Action } from '@ngrx/store';
import { Item } from '...';

export interface ItemAction<T> extends Action {
    payload?: T;
}

/*
 * action types
 */

export const ADD = 'ADD'
export const DELETE = 'DELETE'
export const LOAD_ITEMS = 'LOAD_ITEMS'
export const ITEMS_LOADED = 'ITEMS_LOADED'

/*
 * action creators
 */

export function createAddItemAction(item: Item): ItemAction<Item> {
    return { type: ADD, payload: item }
}

export function createDeleteItemAction(item: Item): ItemAction<Item> {
    return { type: DELETE, payload: item }
}

export function createItemsLoadedAction(items: Item[]): ItemAction<Item[]> {
    return { type: ITEMS_LOADED, payload: items }
}

export function createLoadItemsAction(): ItemAction<Item> {
    return { type: LOAD_ITEMS }
}

Я использую

 "@ngrx/effects": "^4.0.5",
 "@ngrx/store": "^4.0.3",

Что мне не хватает? Моя цель - загрузить элементы, когда компонент загружен.


person Tenoda    schedule 27.08.2017    source источник
comment
обновить пост с помощью ItemAction файла класса   -  person Aravind    schedule 27.08.2017
comment
как вы проверяете, что this.items = this.store.select('items') не работает? Если бы вы могли показать свой шаблон, так как ошибка могла быть там   -  person Meeker    schedule 27.08.2017
comment
довольно сложно увидеть проблему, поэтому было бы лучше, если бы вы могли воспроизвести небольшой плункер. для получения дополнительной информации о ngrx перейдите по этой ссылке   -  person Rahul Singh    schedule 28.08.2017


Ответы (3)


Гм. Если я правильно понимаю, выберите работает по-другому.

Чего ты ждешь сейчас? Как this.store.select('items') это должно работать?

Насколько я понимаю, вам нужно создавать селекторы. Я не уверен, что вы их создали, поскольку я не вижу ни одного из них в предоставленном вами коде. И еще вы странным образом используете select.

Я думаю, что вам не хватает этих селекторов. Ты нуждаешься в этом:

Или вы можете объяснить, чего вы ожидаете от текущего кода? :) Может я чего-то не знаю.

person Sharikov Vladislav    schedule 27.08.2017

Чтобы получить данные, вам нужно использовать селекторы и добавить состояние, как упомянуто А. Мойнетом выше.

https://ngrx.io/guide/store/selectors

Пример ребят из ngrx:

import { createSelector } from '@ngrx/store';

export interface FeatureState {
  counter: number;
}

export interface AppState {
  feature: FeatureState;
}

export const selectFeature = (state: AppState) => state.feature;

export const selectFeatureCount = createSelector(
  selectFeature,
  (state: FeatureState) => state.counter
);

И чтобы использовать это, мы делаем это в компоненте

ngOnInit() {
    this.counter = this.store.pipe(select(fromRoot.selectFeatureCount))
}
person Satpal Tanan    schedule 04.01.2019

Попробуйте определить интерфейс AppState и введите состояние магазина:

interface AppState{
  items: Item[]
}

constructor(private store: Store<AppState>)

Затем не забудьте использовать асинхронный канал в файле шаблона (items | async) или подписаться в файле компонента (но я думаю, вы это знаете)

person A. Moynet    schedule 28.08.2017