gpt4 book ai didi

angular - 使用 featureSelector ngrx 时无法读取未定义 map 的属性

转载 作者:太空狗 更新时间:2023-10-29 17:45:13 25 4
gpt4 key购买 nike

repo :https://github.com/morningharwood/platform/tree/feature/ngrx-firebase

当我尝试订阅我的 selectAll of my post ngrx 实体功能时,出现错误:

Cannot read property of map of undefined

这一定是一个简单的错字,我正在逐字逐句地学习教程。

奇怪的是如果我使用字符串选择器:

 this.selected$ = this.store.select('post');

this.selected$.subscribe(console.log); // no error here.

我没有错误。

问题:使用 ngrx 实体时,如何让我的 selectAll 选择器从 ngrx 存储集合 post 中注销所有帖子?

我的post.reducer.ts

import {
PostActions,
PostActionTypes,
} from './post.actions';

import {
ActionReducerMap,
createFeatureSelector,
} from '@ngrx/store';
import {
createEntityAdapter,
EntityState,
} from '@ngrx/entity';
import { Post } from './post.interfaces';

export const postAdapter = createEntityAdapter<Post>();
export interface PostState extends EntityState<Post> {}

export const postInitialState: PostState = {
ids: [ '1234' ],
entities: {
'1234': {
id: '1234',
header: {
title: 'title 1',
subtitle: 'subtitle 1',
},
body: {
sections: [],
},
},
},
};

export const initialState: PostState = postAdapter.getInitialState(postInitialState);

export function postReducer(state: PostState = initialState, action: PostActions): PostState {
switch (action.type) {
case PostActionTypes.ADD_ONE:
return postAdapter.addOne(action.post, state);
default:
return state;
}
}

export const getPostState = createFeatureSelector<PostState>('post');
export const {
selectIds,
selectEntities,
selectAll: selectAllPosts,
selectTotal,
} = postAdapter.getSelectors(getPostState);

export const postReducersMap: ActionReducerMap<any> = {
post: postReducer,
};

app.component:

import {
Component,
OnInit,
} from '@angular/core';
import { AppState } from './app.interfaces';
import { Store } from '@ngrx/store';
import { selectAllPosts } from './post/post.reducer';

import { Observable } from 'rxjs/Observable';


@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
})
export class AppComponent implements OnInit {
public selected$: Observable<any>;

constructor(private store: Store<AppState>) {
}

ngOnInit() {

this.selected$ = this.store.select(selectAllPosts);
this.selected$.subscribe(console.log); // error here
}
}

我的forFeatureforRoot模块:

@NgModule({
imports: [
BrowserModule.withServerTransition({ appId: 'portfolio-app' }),
StoreModule.forRoot({ reducers }),
EffectsModule.forRoot([]),
PostModule,
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [],
})
export class AppModule {
}

import { StoreModule } from '@ngrx/store';
import { postReducers } from './post.reducer';


@NgModule({
exports: [],
declarations: [],
imports: [StoreModule.forFeature('post', postReducersMap)],
})
export class PostModule {
}

最佳答案

对于以后遇到这个问题的人来说,这可以通过稍微重构选择器来解决。

根据此处的文档(在发布时有些不完整),ngrx.io/entity/adapter ,您需要使用 createFeatureSelector 函数选择 featureSate,然后将该子状态与适配器选择器一起使用以选择该状态的切片。

改变这个:

post.reducer.ts

export const getPostState = createFeatureSelector<PostState>('post');
export const {
selectIds,
selectEntities,
selectAll: selectAllPosts,
selectTotal,
} = postAdapter.getSelectors(getPostState);

为此:

export const selectPostState = createFeatureSelector<PostState>('post');
export const {
selectIds,
selectEntities,
selectAll
selectTotal,
} = postAdapter.getSelectors();

export const selectPostIds = createSelector(
selectPostState,
selectIds
);

export const selectPostEntities = createSelector(
selectPostState,
selectEntities
);

export const selectAllPosts = createSelector(
selectPostState,
selectAll
);

这将选择 postState 功能的子状态。

希望对你有帮助

编辑:所以看起来上面两个例子是等价的,我面临的问题与 Matthew Harwood 相同并且 ActionReducerMap 的使用不当。

我认为文档对此可能有点困惑,因为它们让人相信实体和实体的状态与功能状态(例如延迟加载状态)的状态相同。

虽然实体状态具有 id 和实体等属性,但它们不需要像特征状态那样分别进行归约,而只需要一个归约器来覆盖该模型的所有实体状态。

例如

export const initialState: PostState = postAdapter.getInitialState(postInitialState);

PostAdapterState 不需要缩减器映射,因为只有一个缩减器

export function postReducer(state: PostState = initialState, action: 
PostActions): PostState {
switch (action.type) {
case PostActionTypes.ADD_ONE:
return postAdapter.addOne(action.post, state);
default:
return state;
}
}

涵盖所有实体状态更新。

如果您在一个功能状态中有多个适配器状态,您将需要一个缩减器映射,如下例所示。

假设您有一个图书馆功能状态,以及书籍和杂志的实体。它看起来像下面这样。

book.reducer.ts

export interface BookEntityState extends EntityState<Book> {
selectedBookId: string | null;
}

const bookAdapter: EntityAdapter<Book> = createEntityAdapter<Book>();

export const initialBookState: BookEntityState = adapter.getInitialState({
selectedBookId: null
});

export const bookReducer (...) ... etc

magazine.reducer.ts

export interface MagazineEntityState extends EntityState<Magazine> {
selectedMagazineId: string | null;
}

const magazineAdapter: EntityAdapter<Magazine> = createEntityAdapter<Magazine>();

export const initialMagazineState: MagazineEntityState =
adapter.getInitialState({
selectedMagazineId: null
});

export const magazineReducer (...) ... etc

然后你的库功能状态可能是这样的

library.reducer.ts

// Feature state,
export interface LibraryFeatureState {
books: BookEntityState
magazines: MagazineEntityState
}

// Reducer map of the lirbray
export const libraryReducersMap: ActionReducerMap<LibraryFeatureState> = {
books: bookReducer,
magazines: magazineReducer
};

然后将功能状态添加到 LibraryModule 导入数组中的 Store。

library.module.ts

...
StoreModule.forFeature<LibraryFeatureState>('libraryState',
libraryReducersMap),
...

希望这对其他人有帮助。

关于angular - 使用 featureSelector ngrx 时无法读取未定义 map 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47406386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com