在与NgRx Router Store在同一页面上导航时分派动作



我目前正在使用NgRx和Router Store构建一个应用程序。在一个组件中有一个下拉菜单,它改变了url中的参数,并在同一个组件上导航。因为在同一个组件上导航不会调用NgOnInit,所以不会调用相应的效果(调用API的效果)。在我看来,如果组件改变了参数,则应该始终调用该效果。

loadTransactions$ = createEffect(() => this.actions$.pipe(
ofType(
NavigationActions.ActionType.NavigateToTransactionsSuccess,
TransactionsPageActions.ActionType.LoadPage
),
[...]
));

我有一个想法,是创建一个自定义操作,只监听组件上的导航与下拉菜单,但我不知道如何做到这一点。

我当前的解决方案如下:

this.store.select(RouterSelectors.selectUrl).subscribe(() =>
this.store.dispatch(TransactionsPageActions.loadPage())
);

但这感觉可能会在未来导致一些bug。有什么办法可以干净利落地做到这一点吗?

既然你想通过路由控制数据的加载,那么通过routeguard(特别是CanActivateGuard)来执行transactionData的提取将是理想的和更干净的。

下面是一个可能的方法的简单片段,

routing.module.ts

const routes: Routes = [
{
path: '',
component: ShellPageComponent,
canActivate: [],
children: [
{
path: '',
component: MainParentComponent,
children: [
{
path: ':transactionId',

canActivate: [TransactionGuard],
component:TransactionComponent

},

{ path: '**', redirectTo: 'MainParentComponent' }
]
},

]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class  RoutingModule {}

transaction-page.guard.ts

@Injectable({
providedIn: 'root'
})
export class TransactionGuard implements CanActivate {
constructor( private store: Store<any>  ) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> {

const transcationId = route.paramMap.get('transactionId')
//assuming  TransactionIsLoadedSelector is a selector to verify if transaction has been loaded and returns a Boolean
return this.store.select(TransactionIsLoadedSelector$,{id:transcationId}).pipe(
tap((TransactionIsLoaded)=>{
if(!TransactionIsLoaded){
this.store.dispatch(TransactionsPageActions.loadPage())
}
}),
filter((TransactionIsLoaded)=> TransactionIsLoaded)

)
}
}

我更仔细地阅读了文档,效果指南告诉你以下内容:

注意:事件流并不局限于分派的动作,它可以是任何产生新动作的可观察对象,比如Angular Router中的可观察对象、从浏览器事件中创建的可观察对象,以及其他可观察流。

所以我实现了一个自定义的路由器动作,并在一个效果中调度它,当路由器存储中的accountId发生变化时调用它。

accountIdChanged$ = createEffect(() => this.store.select(
RouterSelectors.selectRouteParam('accountId')
).pipe(
map((accountId) => RouterActions.accountIdChanged({accountId}))
));

现在我可以在任何我想要的地方听到这个动作,例如在我的事务效果。

loadTransactions$ = createEffect(() => this.actions$.pipe(
ofType(RouterActions.ActionType.AccountIdChanged),
// [...]
));

相关内容

  • 没有找到相关文章

最新更新