問題描述
如何防止在 NgRx 中第二次加載數據? (How prevent loading data second time in NgRx?)
我有一個 DOM 塊:
<div (click)="toggle(block)">
<div *ngIf="block.opened">
<div *ngFor="let item of block.items"></div>
</div>
</div>
通過單擊我調度操作以從服務器加載數據並在塊中顯示此數據:
toggle(block: RegistryGroup) {
this.store.dispatch(RegistryActions.ToggleRegistryBlockAction(block));
this.store.dispatch(RegistryActions.LoadRegistryLayersAction(this.block));
}
第一個事件 ToggleRegistryBlockAction 將
block
的屬性更改為 true/false。第二個LoadRegistryLayersAction
通過block.id
向服務器發出請求,並將數據返回到與block
相同的狀態到屬性block。 items = 服務器響應;
在我偵聽動作的效果方面 LoadRegistryLayersAction
:
loadRegistriesLayers$: Observable<Action> = createEffect(() =>
this.actions$.pipe(
ofType(RegistryActions.LoadRegistryLayersAction),
filter(
(registryGroup) =>
registryGroup.items && !registryGroup.items.length
),
switchMap((registryGroup: RegistryGroup) =>
from(this.registry.getRegistryLayers(registryGroup.Id)).pipe(
map((layers: { [key: string]: RegistryLayerItemGeneric[] }) => {
return RegistryActions.SuccessLoadRegistryLayersAction({
payload: {
layers: this.registry.createLayersMapWithObjects(layers),
registryGroupId: registryGroup.Id,
},
});
}),
catchError((error: Error) => {
return of(RegistryActions.ErrorRegistryLayersAction(error));
})
)
)
)
);
I filter
動作並檢查數據是否已經存在。為此,我檢查塊是否有 registryGroup.items & && !registryGroup.items.length
.
問題是有時在執行後這個效果服務器會返回空的[]
。所以下一次,當用戶請求它時,它會重複發送請求。
如果加載了數據,如何修復它並且不接觸服務器?
參考解法
方法 1:
There are multiple solutions:
- keep a status property which can be
loading
, loaded
, empty
,... - keep a list of id's that are fetched in the state, and check this list before sending the request
- don't check on
registryGroup.items.length
, and initialize the array as null
方法 2:
Try the ngrx‑loading‑state lib:
https://github.com/amzhang/ngrx‑loading‑state
Live demo to avoid issuing API load multiple times:
https://stackblitz.com/edit/angular‑ivy‑rocjzb?file=src%2Fapp%2Fapp.component.ts
You you are after is to use the NgRx store as a cache. So somewhere we need to track the age or the presence of the last successful load. The above lib does the heavy lifting of deciding if an API call is necessary based on a maxAge
parameter. Look for the filterLoading()
function in the effects. That's where the checking happens.
It's boilerplatey, NgRx always is. But it offers consistency and a pattern to follow.
(by user15172022、timdeschryver、flux)
參考文件