Как получить и обновить данные из хранилища ngrx в переменную Observable? - PullRequest
0 голосов
/ 28 марта 2019

Я получил довольно простой функциональный модуль с хранилищем / редукторами / и т. Д., Созданный @ ngrx / schematics.В этом функциональном модуле я получил 2 компонента - форму и список элементов, который по умолчанию пуст, и вы можете добавлять элементы через форму.Когда я добавляю что-то через действие формы, редуктор получает полезную нагрузку, но список элементов во втором компоненте не обновляется.

список элементов html:

<section class="sub-list">
  <div class="container">
    <header class="sub-list--header"><h1>My Subscriptions</h1></header>
    <span *ngIf="length$ | async">Subscriptions count - {{ length$ | async }}</span>
    <main class="sub-list--content" *ngIf="list$ | async as list">
      <div class="sub-list--item" *ngFor="let item of list">
        <div class="name">{{ item.name }}</div>
      </div>
    </main>
  </div>
</section>

элемент списка элементов:

import { Component, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';

// Store
import * as fromSub from '../../reducers/subscription.reducer';
import * as subActions from '../../actions/subscription.actions';
// Models
import { Subscription } from '../../models/Subscription';

@Component({
  selector: 'app-sub-list',
  templateUrl: './sub-list.component.html',
  styleUrls: ['./sub-list.component.scss']
})
export class SubListComponent implements OnInit {
  list$: Observable<Subscription[]>;
  length$: Observable<number>;
  constructor(
    private snackBar: MatSnackBar,
    private subStore: Store<fromSub.State>
  ) {
    this.list$ = this.subStore.select('subscriptionsList');
    this.length$ = this.subStore.select('length');
  }

  ngOnInit() {
  }

}

компонент формы (на случай, если я неправильно отправил действие):

import { Component, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import { Store } from '@ngrx/store';

// Store
import * as fromSub from '../../reducers/subscription.reducer';
import * as subActions from '../../actions/subscription.actions';
// Models
import { Subscription } from '../../models/Subscription';

@Component({
  selector: 'app-sub-form',
  templateUrl: './sub-form.component.html',
  styleUrls: ['./sub-form.component.scss']
})
export class SubFormComponent implements OnInit {
  name: string;
  price: number;
  link: string;
  date: Date;
  constructor(
    private snackBar: MatSnackBar,
    private subStore: Store<fromSub.State>
  ) {
    this.price = 0;
  }

  ngOnInit() {
  }

  addSubscription = (): void => {
    // Snackbar test
    if (!this.name) {
      this.snackBar.open('Name field is empty', 'Close', { duration: 3000 });
      return;
    }
    // if (this.link === '') {}
    if (this.price < 0) {
      return;
    }
    if (!this.date) {
      this.snackBar.open('Date field is empty', 'Close', { duration: 3000 });
      return;
    }
    const newSub: Subscription = {
      name: this.name,
      price: this.price,
      link: this.link,
      date: this.date,
    };
    this.subStore.dispatch(new subActions.AddSubscription(newSub));
    this.snackBar.open('Subscription added', 'Close', { duration: 3000 });
  }
}

модуль редуктора:

import { SubscriptionActions, SubscriptionActionTypes } from '../actions/subscription.actions';
import { Subscription } from '../models/Subscription';

export interface State {
  length: number;
  subscriptionsList: Subscription[];
}

export const initialState: State = {
  length: 0,
  subscriptionsList: [],
};

export function reducer(state = initialState, action: SubscriptionActions): State {
  switch (action.type) {

    case SubscriptionActionTypes.LoadSubscriptions:
      return state;

    case SubscriptionActionTypes.AddSubscription:
      return Object.assign({}, state, {
        subscriptionsList: state.subscriptionsList.concat(action.payload),
        length: state.subscriptionsList.length + 1
      });

    default:
      return state;
  }
}

Так что это может быть проблема в редукторе (неправильное обновление магазина) или в компоненте (неправильный выбор или неправильный поставщик)

1 Ответ

0 голосов
/ 29 марта 2019

Сначала думает первым:

Ваш глобальный магазин выглядит так:

interface RootStore {
  subscription: {
    subscriptionsList: Array<...>,
    length: number;
  }
}

Поэтому, когда вы хотите получить this.lenght$ в компоненте, вы должны сделать это:

this.lenght$ = this.store.select(rootStore => rootStore.subscription.lenght)

Когда вы подписываетесь на хранилище в компоненте, вы пытаетесь получить ключ length в RootStore.Его не существует, поэтому вы подписываетесь на undefined.После действия отправки оно все еще не определено, поэтому компонент не обновил данные.

...