簡體   English   中英

即使已加載數據,選擇的角度 ngrx 防護也未定義

[英]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;
  }
);

更新2

它與

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM