如何从 ngrx 存储中获取数据并将其更新到 Observable 变量中?
Posted
技术标签:
【中文标题】如何从 ngrx 存储中获取数据并将其更新到 Observable 变量中?【英文标题】:How to get and update data from the ngrx store into Observable variable? 【发布时间】: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, ]
【参考方案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 => rootStore.subscriptionsList); this.length$ = this.subStore.select(rootStore => rootStore.length);
也许是因为我的 index.ts 是空的? this.lenght$ = this.store.select(rootStore => rootStore.subscription.lenght)
中存储的是什么?以上是关于如何从 ngrx 存储中获取数据并将其更新到 Observable 变量中?的主要内容,如果未能解决你的问题,请参考以下文章
如何处理来自 ngrx effect 的 catch 块的错误并将其发送到组件中?
如何从 Apple Watch 获取实时健康更新,与健康工具包同步并将其发送到服务器?