【问题标题】:How to get and update data from the ngrx store into Observable variable?如何从 ngrx 存储中获取数据并将其更新到 Observable 变量中?
【发布时间】:2019-08-19 18:02:52
【问题描述】:

我得到了由@ngrx/schematics 创建的包含 store/reducers/etc 的非常简单的功能模块。在此功能模块中,我有 2 个组件 - 表单和项目列表,默认情况下为空,您可以通过表单添加项目。当我通过表单操作添加内容时,reducer 获取有效负载,但第二个组件中的项目列表不会更新。

项目列表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;
  }
}

所以可能是reducer(错误的商店更新)或组件(错误的选择或错误的提供者)中的问题

【问题讨论】:

  • 是你的空洞状态{ subscriptionsList: Array, lenght: number },你在rootStore中没有任何功能吗?
  • @PrzemyslawPietrzak 是的,这个应用程序就像简单的待办事项列表,我在上面学习 angular 和 ngrx 的基础知识。所以基本上我有一个项目列表和表格来填写这个列表。
  • 好的,请在您将减速器与角度模块连接的位置粘贴部分代码
  • @PrzemyslawPietrzak 好的,这是我的模块:import * as fromSubscription from './reducers/subscription.reducer'; import { EffectsModule } from '@ngrx/effects'; import { SubscriptionEffects } from './effects/subscription.effects'; @NgModule({ declarations: [SubFormComponent, SubListComponent], imports: [ CommonModule, FormsModule, MaterialModule, StoreModule.forFeature('subscription', fromSubscription.reducer), EffectsModule.forFeature([SubscriptionEffects]), ], exports: [ SubFormComponent, SubListComponent, ]

标签: angular ecmascript-6 store ngrx ngrx-store


【解决方案1】:

先想先:

您的全球商店如下所示:

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

所以当你想在组件中获取 this.lenght$ 时,你必须这样做:

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

当您订阅组件中的存储时,您会尝试在 RootStore 上获取 length 键。它不存在,所以你订阅了 undefined。在调度操作之后它仍然是未定义的,所以你的组件没有刷新数据。

【讨论】:

  • 我没有根存储,现在我只有模块存储,它直接进入组件
  • 你在商店注册reducer时成功了,签入redux开发工具
  • 那么我是否理解正确,我所需要的只是将我的 featureModule 存储注册到 rootStore 中?
  • 您已经做到了:StoreModule.forFeature('subscription', fromSubscription.reducer) 表示您在商店中注册了subscription 功能,并使用fromSubscription.reducer。所以唯一要做的就是在组件中选择你想要的东西,而不是从 RootStore,而不是从 subscription subState
  • 不能像这样工作:this.list$ = this.subStore.select(rootStore =&gt; rootStore.subscriptionsList); this.length$ = this.subStore.select(rootStore =&gt; rootStore.length); 也许是因为我的 index.ts 是空的? this.lenght$ = this.store.select(rootStore =&gt; rootStore.subscription.lenght) 中存储的是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
相关资源
最近更新 更多