一部のコンポーネントで使用される静的なデータセット、国のリストがあります。このデータは、これらのコンポーネントのngOnInit()
に読み込まれますが、データを要求するのが初めての場合(ストアが空)にのみ読み込みたいと思います。それ以降は、コンポーネントをロードするたびに、ストアからのデータを「更新」せずに単に使用したいだけです。
これはngrxを使用してどのように実現できますか?
エフェクトを使用しています。これは私のコードがどのように見えるかです:
コンポーネント:
export class EditPageComponent implements OnInit {
countries$: Observable<Country[]>
constructor(private store: Store<fromContacts.State>) {
this.countries$ = store.select(fromContacts.getCountriesEntities);
}
ngOnInit() {
this.store.dispatch(new countries.Load());
}
の効果:
@Effect()
loadCollection$: Observable<Action> = this.actions$
.ofType(countries.LOAD)
.switchMap(() =>
this.countriesService
.getCountries()
.map((countriesList: Country[]) => {
return new countries.LoadSuccess(countriesList);
})
.catch(error => of(new countries.LoadFail(error)))
);
そしてレデューサー:
case countries.LOAD_SUCCESS: {
const countriesList: Country[] = action.payload;
const reducedCountries: { [id: string]: Country } = countriesList.reduce((countrs: { [id: string]: Country }, countr: Country) => {
return Object.assign(countrs, {
[countr.code]: countr
});
}, {});
ありがとう、ガブ
これにはさまざまな方法があります。まず最初に、hasLoaded: boolean
状態のプロパティ。その後、サービスのget呼び出しを行う前にこれを確認できます。
ngOnInit() {
this.store.select(getHasLoaded)
.take(1)
.subscribe(hasLoaded => {
if (!hasLoaded) this.store.dispatch(new countries.Load());
}
}
別のオプションは、@ EffectにhasLoadedプロパティをチェックさせることです。
@Effect()
loadCollection$: Observable<Action> = this.actions$
.ofType(countries.LOAD)
.withLatestFrom(this.store.select(getHasLoaded)
.filter(([ action, hasLoaded ]) => !hasLoaded) // only continue if hasLoaded is false
.switchMap(() =>
this.countriesService
.getCountries()
.map((countriesList: Country[]) => {
return new countries.LoadSuccess(countriesList);
})
.catch(error => of(new countries.LoadFail(error)))
);
これを機能させるには、Effectsコンストラクターにストアを提供する必要があります。
take(1)
演算子を使用する
catchError
を使用したエラー処理を忘れずにEMPTY
を返します。それ以外の場合、エラーが発生すると、そのエラーが常に返されます(タイムアウト、認証エラー、オフライン...)
私はあなたとまったく同じケースを抱えていました。私がしたことは、rxjs演算子take
を追加して、LoadCountries
アクションがディスパッチされたときに初めて国を取得することでした。
_@Effect()
loadCountries$: Observable<CoreActions> = this.actions$.pipe(
ofType(CoreActionTypes.LoadCountries),
mergeMap(() =>
this.countriesService.getAllCountries().pipe(
map(c => new LoadCountriesSuccess(c)),
catchError(() => {
this.store.dispatch(new LoadCountriesFailed());
return EMPTY;
})
)
),
take(1)
);
_
EMPTY
の内部でcatchError
を返すと、take(1)
を経由せずにオブザーバブルが完了します
ストア内で国が選択されている場合は、それらがストアに表示されている場合はアクションを無視し、そうでない場合は国をフェッチします。
@Effect()
getOrder = this.actions.pipe(
ofType<GetOrder>(ActionTypes.GetOrder),
withLatestFrom(this.store.pipe(select(getOrders))),
filter(([{payload}, orders]) => !!orders[payload.orderId])
mergeMap([{payload}] => {
...
})
)
詳細については、 このためのngrx/effectsの使用を開始 を参照してください。
私の答えはHetty de Vries
回答。エフェクトに触れずに単にストアのコンテンツを取得したい場合は、次のようなことができます。
this.store.select(state => state.producer.id).forEach( id => {
...
}
ストアにproducer
属性を持つid
オブジェクトが含まれているとします。