[英]Angular ngrx guard selected is undefined even if data has been loaded
我有這個減速機
on(CmsActions.loadCmsTopNewsSelected, (state, { slug }) => {
let selected;
if (state.data) {
selected = state.data.items.find(item => item.data.slug.iv === slug);
}
return {
...state,
selected
};
})
還有這個守衛
canActivate(route: ActivatedRouteSnapshot): Observable<boolean | UrlTree> {
return this.checkStore().pipe(
switchMap(() => {
const slug = route.params.slug;
this.facade.selected(slug);
return this.facade.selected$.pipe(
map(selected => {
console.log('selected', selected);
if (selected) {
return true;
}
return this.router.parseUrl('/not-found');
})
);
}),
catchError(() => of(false))
);
}
checkStore(): Observable<boolean> {
return this.facade.loaded$.pipe(
tap(loaded => {
if (!loaded) {
this.facade.load(this.ITEMS_TO_LOAD);
}
}),
filter(loaded => {
console.log('loaded', loaded);
return loaded;
}),
take(1)
);
}
如果我通過路由器鏈接轉到路線,效果很好,
但如果我直接去選擇是未定義的,即使
數據已加載。
怎么了?
我發布了更多代碼以便更好地理解順便說一句,當瀏覽器運行子路由時,我正在等待加載數據。
路由父級
{
path: 'news',
canLoad: [CmsNewsGuard],
loadChildren: () =>
import('./news/news.module').then(m => m.PublicNewsModule)
},
孩子們
{
path: ':slug',
canActivate: [CmsNewsGuardSelected],
component: PublicNewsPageDetailsComponent
},
{
path: '',
component: PublicNewsListComponent,
pathMatch: 'full'
}
正面
export class CmsNewsFacade {
get data$(): Observable<CmsArray<CmsNews> | null> {
return this.store.pipe(select(selectCmsNewsData));
}
get error$(): Observable<Required<ErrorDto> | null> {
return this.store.pipe(select(selectCmsNewsError));
}
get loaded$(): Observable<boolean> {
return this.store.pipe(select(selectCmsNewsLoaded));
}
get selected$(): Observable<CmsNews | undefined> {
return this.store.pipe(select(selectCmsNewsSelected));
}
constructor(private store: Store<CmsState>) {}
load(top: number): void {
this.store.dispatch(CmsActions.loadCmsTopNews({ top }));
}
selected(slug: string): void {
this.store.dispatch(CmsActions.loadCmsTopNewsSelected({ slug }));
}
}
選擇器
export const selectCmsNewsSelected = createSelector(
selectMarketAccountFeature,
(state: CmsState) => {
return state.news.selected;
}
);
它與
return this.facade.selected$.pipe(
filter(selected => {
return !!selected;
}),
map(selected => {
if (selected) {
return true;
}
return this.router.parseUrl('/not-found');
})
);
但是這樣做我失去了目標,如果 slug 不存在,則顯示未找到的頁面:(
我想出了在減速器中添加檢查的方法
const current = state.data.items.find(item => item.data.slug.iv === slug);
if (!current) {
selected = null;
}
在衛兵簡直
filter(selected => {
return selected !== undefined;
}),
我認為您的選擇器試圖選擇一個未定義的狀態,因為當您的頁面加載時,您的 Guard 檢查條件的速度比加載后數據在商店中的出現速度更快。 這是因為懶加載。 您的 Guard 在預先加載的模塊中提供。 您的商店部分是在延遲加載的模塊中聲明的,這就是為什么您的 Guard 在首次加載時不接受您的導航的問題。
你如何解決這個問題?
檢查您的狀態何時未定義,在這種情況下返回 true,當您的狀態進行更新時,如果您的用戶沒有訪問權限,您的守衛將重定向您的用戶。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.