javascript - NgRx Store - 根据另一个状态对象的属性有条件地加载数据
问题描述
我有一个应用程序,它根据季节 id 从我的 API 呈现固定装置、结果等 - 此 id 作为 SeasonState 的属性存储在 state 中:
export interface SeasonsState extends EntityState<Season> {
allSeasonsLoaded: boolean;
currentlySelectedSeasonId: number;
}
其他组件使用它来确定从 API 获取哪些夹具、结果等并存储在状态中。例如:
this.store
.pipe(
select(selectCurrentlySelectedSeason)
).subscribe(seasonId => {
this.store.dispatch(new AllFixturesBySeasonRequested({seasonId}));
this.fixtures$ = this.store
.pipe(
select(selectAllFixturesFromSeason(seasonId))
);
});
这很好用,但我真正想要的是能够再次获取固定装置,该特定季节的固定装置尚未存储在状态中。
我尝试创建一个选择器,用于在我的效果中有条件地从 API 加载数据:
export const selectSeasonsLoaded = (seasonId: any) => createSelector(
selectFixturesState,
fixturesState => fixturesState.seasonsLoaded.find(seasonId)
);
但我不确定如何实现这个/这是否是正确的方法。
编辑:使用下面答案中的信息,我编写了以下效果,但是请参阅评论 - 我需要能够在我的 withLatestFrom 中使用有效负载中的 seasonId。
@Effect()
loadFixturesBySeason$ = this.actions$
.pipe(
ofType<AllFixturesBySeasonRequested>(FixtureActionTypes.AllFixturesBySeasonRequested),
withLatestFrom(this.store.select(selectAllFixtures)), // needs to be bySeasonId
switchMap(([action, fixtures]) => {
if (fixtures.length) {
return [];
}
return this.fixtureService.getFixturesBySeason(action.payload.seasonId);
}),
map(fixtures => new AllFixturesBySeasonLoaded({fixtures}))
);
解决方案
有这样的效果设置[我使用的是ngrx 6,因此在ngrx 6上进行了测试;如果您使用的是其他版本,那么您会有所了解并相应地调整代码] -
@Effect() allFixturesBySeasonRequested: Observable<Action> =
this._actions$
.pipe(
//Please use your action here;
ofType(actions.AllFixturesBySeasonRequested),
//please adjust your action payload here as per your code
//bottom line is to map your dispatched action to the action's payload
map(action => action.payload ),
switchMap(seasonId => {
//first get the fixtures for the seasonId from the store
//check its value if there are fixtures for the specified seasonId
//then dont fetch it from the server; If NO fixtures then fetch the same from the server
return this.store
.pipe(
select(selectAllFixturesFromSeason(seasonId)),
//this will ensure not to trigger this again when you update the fixtures in your store after fetching from the backend.
take(1),
mergeMap(fixtures => {
//check here if fixtures has something OR have your logic to know
//if fixtures are there
//I am assuming it is an array
if (fixtures && fixtures.lenght) {
//here you can either return NO action or return an action
//which informs that fixtures already there
//or send action as per your app logic
return [];
} else {
//NO fixtures in the store for seasonId; get it from there server
return this.http.get(/*your URL to get the fixtures from the backend*/)=
.pipe(
mergeMap(res => {
return [new YourFixtureFetchedSucccess()];
}
)
)
}
})
);
})
)
现在,您需要调度从您的服务/组件或您的应用程序设计方式中获取指定 seasonId 灯具的操作。
希望它会给您一个想法并帮助您解决问题。
推荐阅读
- php - 如何获取以逗号分隔的数据并将其存储在复选框中,如在 php 中选中
- zabbix - Zabbix - 难以聚合使用 UserParameter 生成的数据
- html - 如何使 CSS 背景响应特定尺寸
- import - 将 FTP 文件夹中的源代码导入 VSTS
- c++ - for循环异常c ++
- ios - iOS AVPlayer 不播放所有远程文件
- php - PHPMailer 向同一收件人发送重复的电子邮件,但使用不同的随机生成代码进行电子邮件验证
- php - 如何在自定义帖子类型中获取帖子类别
- java - 如何检查jsp是否进入spring mvc中的控制器以及如何从控制器显示列表到jsp?
- neo4j - Neo4J 抛出 IOException 然后定期停止