NgRx: получить данные из хранилища, но они не определены - PullRequest
0 голосов
/ 16 октября 2018

Уважаемое сообщество Stackoverflow.

Я новичок в NgRx и пытаюсь выяснить, как это работает.Я создаю приложение - простой список покупок, основанный на Angular 6, Firebase и NgRx.

Я добавил пару элементов в коллекцию под названием Product и пытаюсь получить их с помощью шаблонов ngrx.Кажется, я все сделал хорошо - я выбрал элементы в качестве полезной нагрузки в GET_PRODUCTS_SUCCESS, но я не могу поместить их в представление для отображения, продукты не определены.Я пытался сделать это двумя способами:

this.store.select(getProducts).subscribe(products => {
  console.log('products', products); // undefined
});

и

 this.products = this.store.select(getProducts); // Store

Вторым способом я просто получаю целый магазин ... Код ниже.

продукт.actions.ts

import { Action } from '@ngrx/store';
import { Product } from '../../models/product.model';

export const GET_PRODUCTS = 'Get_products';
export const GET_PRODUCTS_SUCCESS = 'Get_products_success';

export class GetProducts implements Action {
  readonly type = GET_PRODUCTS;
  constructor(public payload = '') {}
}

export class GetProductsSuccess implements Action {
  readonly type = GET_PRODUCTS_SUCCESS;
  constructor(public payload?: Product[]) {}
}

export type Actions = GetProducts | GetProductsSuccess;

product.reducer.ts

import { Product } from '../../models/product.model';
import * as productAction from './products.action';

export interface State {
  products: Product[];
  loading: boolean;
}

export const initialState: State = {
  products: [],
  loading: false,
};

export function ProductsReducer(state: State = initialState, action: productAction.Actions) {

  switch (action.type) {
    case productAction.GET_PRODUCTS:
      return {...state, loading: true};

    case productAction.GET_PRODUCTS_SUCCESS:
      const test = {...state, products: action.payload, loading: false};
      console.log("test", test);
      return test;

    default:
        return state;
  }
}

enter image description here

product.effects.ts

import { Injectable } from '@angular/core';
import { Action } from '@ngrx/store';
import { Effect, Actions } from '@ngrx/effects';
import { AngularFirestore } from '@angular/fire/firestore';

import { Product } from '../../models/product.model';
import * as productAction from './products.action';

import { Observable, of } from 'rxjs';
import { switchMap, map, mergeMap } from 'rxjs/operators';


@Injectable()
export class ProductEffects {

  constructor(private actions$: Actions, private db: AngularFirestore) {}

  @Effect()
  getProducts: Observable<Action> = this.actions$
    .ofType(productAction.GET_PRODUCTS).pipe(
      switchMap(() => {
        return this.db.collection<Product>('products').valueChanges()
        .pipe(
          map((payload) => {
            return {
              type: 'Get_products_success',
              payload: payload
            };
          })
        );
      })
    );
}

product.selector.ts

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

import { State } from './products.reducer';
import { Product } from '../../models/product.model';

export function getState(state: State): State {
    return state;
}

export function fetchProducts(state: State): Product[] {
    return state.products;
}

export const getProducts = createSelector(getState, fetchProducts);

list.component.ts - получить и отобразить все продукты

import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Product } from '../../models/product.model';
import * as productActions from '../../store/products/products.action';
import { State } from '../../store/products/products.reducer';
import { getProducts } from '../../store/products/products.selector';

import { Observable } from 'rxjs';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit {

  products: Observable<Product[]>;

  constructor(private store: Store<State>) {}

  ngOnInit() {
    this.store.dispatch(new productActions.GetProducts);
    this.store.select(getProducts).subscribe(products => {
      console.log('products', products);
    });

  }

}

Если вы заметили, что я что-то не так делаю -не стесняйся сказать мне.Мне действительно нужна твоя помощь.Спасибо.

1 Ответ

0 голосов
/ 17 октября 2018

Я узнал

Я посмотрел, как еще можно запросить мои данные из хранилища.Я нашел один способ, в контексте моего приложения это выглядит так:

 this.store.select(state => state).subscribe(data => {
  console.log('data', data);
});

И я получаю в консоли объект:

{ message: { Products: Array[3], loading: false } }

Что означает это сообщение?Я сделал глобальный поиск и увидел, что мой редуктор реализован в app.module.ts как:

StoreModule.forRoot({ message: ProductReducer }),

. Поэтому я создал index.ts в папке редукторов и экспортировал нижеприведенный редуктор:

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

import * as fromProducts from './products.reducer';

export interface AppState {
    products: fromProducts.ProductState;
}

export const reducers: ActionReducerMap<AppState> = {
    products: fromProducts.productsReducer
};

А теперь в app.module.ts он импортируется как:

    StoreModule.forRoot(reducers),

, и теперь этот код работает хорошо:

this.store.select(getProducts).subscribe(products => {
  console.log('products', products);
});
...