使用 ngrx-router & ngrx-data 的问题
Issue using 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),
文章-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>>', gave the following error.
Argument of type 'MemoizedSelector<RootState, Article | undefined, DefaultProjectorFn<Article | undefined>>' is not assignable to parameter of type 'string | number'.
Type 'MemoizedSelector<RootState, Article | undefined, DefaultProjectorFn<Article | undefined>>' is not assignable to type 'number'.
在我的 article-collections.service.ts
中,我收到了这个我不明白的错误。查了一下好像和接口声明错误有关,但是我没搞明白是哪里做错了。
我不确定您是否已经这样做了,但我建议您创建一个自定义 url 序列化程序,这样您就可以更好地控制发送到路由器存储的内容。
自定义-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;
});
我目前在 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),
文章-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>>', gave the following error.
Argument of type 'MemoizedSelector<RootState, Article | undefined, DefaultProjectorFn<Article | undefined>>' is not assignable to parameter of type 'string | number'.
Type 'MemoizedSelector<RootState, Article | undefined, DefaultProjectorFn<Article | undefined>>' is not assignable to type 'number'.
在我的 article-collections.service.ts
中,我收到了这个我不明白的错误。查了一下好像和接口声明错误有关,但是我没搞明白是哪里做错了。
我不确定您是否已经这样做了,但我建议您创建一个自定义 url 序列化程序,这样您就可以更好地控制发送到路由器存储的内容。
自定义-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;
});