使用 ngrx-router 和 ngrx-data 的问题

问题描述

我目前在我的 angular 12 应用中使用 ngrx。我试图了解如何一起使用 ngrx-router 和 ngrx-data。

我有几个文件

app.module.ts(有趣的行)

/**
 * Store Modules
 */
StoreModule.forRoot(reducers,{ MetaReducers }),StoreDevtoolsModule.instrument({ maxAge: 25 }),EffectsModule.forRoot([RouterEffects]),StoreRouterConnectingModule.forRoot({ routerState: RouterStateMinimal }),EntityDataModule.forRoot(entityConfig),

article-collections.service.ts

import { Injectable } from '@angular/core';
import {
  EntityCollectionServiceBase,EntityCollectionServiceElementsFactory,} from '@ngrx/data';
import { Observable } from 'rxjs';
import { Article } from '../models/articles/article';
import * as fromArticle from '../store/article/article.selectors';

@Injectable({ providedIn: 'root' })
export class ArticleCollectionService extends EntityCollectionServiceBase<Article> {
  active$: Observable<Article>;

  constructor(elementsFactory: EntityCollectionServiceElementsFactory) {
    super('Article',elementsFactory);
    this.active$ = this.store.select(fromArticle.selectActive);
  }
}

index.ts

import { routerReducer,RouterReducerState } from '@ngrx/router-store';
import { ActionReducerMap,MetaReducer } from '@ngrx/store';
import { navigationReducer } from './navigation/navigation.reducer';
import { NavigationState } from './navigation/navigation.state';

export interface RootState {
  router: RouterReducerState;
  navigation: NavigationState;
}

export const reducers: ActionReducerMap<RootState> = {
  router: routerReducer,navigation: navigationReducer,};

export const MetaReducers: MetaReducer[] = [];

router.selectors.ts

    import { getSelectors } from '@ngrx/router-store';
    import { RootState } from '..';
    
    export const selectFeature = (state: RootState) => state.router;
    
    export const {
        selectCurrentRoute,selectFragment,selectQueryParams,selectQueryParam,selectRouteParams,selectRouteParam,selectRouteData,selectUrl,} = getSelectors(selectFeature);

article.selectors.ts

import { EntitySelectorsFactory } from '@ngrx/data';
import { createSelector } from '@ngrx/store';
import { Article } from '../../models/articles/article';
import * as fromrouter from '../router/router.selectors';

export const {
  selectEntities,selectEntityMap,} = new EntitySelectorsFactory().create<Article>('Article');

export interface ArticleStats {
  total: number;
}

export const selectStats = createSelector(
  selectEntities,(articles): ArticleStats => {
    return {
      total: articles.length,};
  }
);

export const selectActiveId = fromrouter.selectRouteParam('id');

export const selectActive = createSelector(
  selectEntityMap,selectActiveId,(entities,id) => entities[id!]
);

在最后一个文件中,我添加entities[id!] 因为 selectRouteParam('id') 给了我未定义的可能结果。我想这是有道理的,因为 url id 并不总是被定义

这一行 this.active$ = this.store.select(fromArticle.selectActive); 产生以下错误

No overload matches this call.
  Overload 1 of 9,'(mapFn: (state: EntityCache) => Article | undefined): Observable<Article | undefined>',gave the following error.
    Argument of type 'MemoizedSelector<RootState,Article | undefined,DefaultProjectorFn<Article | undefined>>' is not assignable to parameter of type '(state: EntityCache) => Article | undefined'.
      Types of parameters 'state' and 'state' are incompatible.
        Type 'EntityCache' is missing the following properties from type 'RootState': router,navigation
  Overload 2 of 9,'(key: string | number): Observable<EntityCollection<any>>',DefaultProjectorFn<Article | undefined>>' is not assignable to parameter of type 'string | number'.
      Type 'MemoizedSelector<RootState,DefaultProjectorFn<Article | undefined>>' is not assignable to type 'number'.

在我的 article-collections.service.ts 中,我收到了这个我不明白的错误。查找后似乎与错误的接口声明有关,但我无法理解我哪里做错了。

解决方法

我不确定您是否已经这样做了,但我建议您创建一个自定义 url 序列化程序,这样您就可以更好地控制发送到路由器存储的内容。

custom-url-serializer.ts

import { RouterStateSerializer } from '@ngrx/router-store';
import { Params,RouterStateSnapshot } from '@angular/router';

export interface CustomRouterStateUrl {
 url: string;
 params: Params;
 queryParams: Params;
}

export class CustomSerializerUrl implements RouterStateSerializer<CustomRouterStateUrl> {
  serialize(routerState: RouterStateSnapshot): CustomRouterStateUrl {
    let route = routerState.root;

    while (route.firstChild) {
      route = route.firstChild;
    }

    const { url,root: { queryParams }} = routerState;
    const { params } = route;

    return { url,params,queryParams };
  }
}

您需要在路由器存储选择器中使用此序列化程序

import { CustomRouterStateUrl} from './custom-url-serializer';
import { RouterReducerState } from '@ngrx/router-store';
import { createFeatureSelector,createSelector } from '@ngrx/store';
export const getRouterState = createFeatureSelector<
  RouterReducerState<CustomRouterStateUrl>
>('router');

export const getCurrentRoute = createSelector(getRouterState,(router) => {
  return router.state;
});

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...