ngrx store - select 一个实体显示在一个单独的模板中
ngrx store - select one entity to show in a separated template
我有一个博客应用程序,我正在使用 ngrx。
应用程序 - 现在 - 在商店中有两个对象
{
"posts": [...],
"users": [...]
}
现在我想制作一个单独的组件来显示单个 post (selected-post.component).
我尝试 select 使用实体的 ID select 或者像这样:
export const selectPostById = (id: string) => createSelector(
selectEntities,
entities => entities[id]
);
然后在组件中获取:
postId: string = localStorage.getItem("_selectedPostId");
selectedPost: Observable<Post> = this.store.select(selectPostById(postId));
然后在我使用的视图中显示它:
<ng-container *ngIf="selectedPost | async">
<div class="post text-light">
<div class="p-title fs-3">{{(selectedPost | async).title}}</div>
<div class="p-image">
<img [src]="(selectedPost | async).imageSrc">
</div>
<div class="p-cont fs-5">
{{(selectedPost | async).content}}
</div>
<div class="p-category float-start fs-6">
<a class="p-1" href="categories/category" *ngFor="let ct of (selectedPost | async).categories">
{{ct}}
</a>
</div>
<div class="p-date float-end fs-6">
{{(selectedPost | async).date}}
</div>
<div class="p-author fs-6">
<a href="users/otheruser">{{(selectedPost | async).author.name}}</a>
</div>
</div>
<div class="info">Comments</div>
<div class="comments text-light">
<div class="comment border rounded m-1" *ngFor="let comment of (selectedPost | async).comments">
<div class="c-author">
<a href="users/otheruser">{{comment.author.name}}</a>
</div>
<div class="c-cont">{{comment.content}}</div>
<div class="-c-date">{{comment.date}}</div>
<div class="replies" *ngIf="comment.replies">
<div class="comment border rounded m-1" *ngFor="let reply of comment.replies">
<div class="c-author">
<a href="users/otheruser">{{reply.author.name}}</a>
</div>
<div class="c-cont">{{reply.content}}</div>
<div class="c-date">{{reply.date}}</div>
</div>
</div>
</div>
</div>
</ng-container>
所以问题是 post 在控制台中没有显示错误:
ERROR TypeError: Cannot read properties of undefined (reading: '1')
我select编辑了ID为“1”的post,它存在于redux devtools显示的状态中。
有什么想法吗?
编辑:
减速器:
import { Action, createFeatureSelector, createReducer, createSelector, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import * as postActions from './actions';
import { Post } from 'src/app/models/post';
export interface PostState extends EntityState<Post> {
error: any;
selectedPostId: string | null;
}
export function selectUserId(a: Post): string {
return a.id;
}
export const adapter: EntityAdapter<Post> = createEntityAdapter<Post>({
selectId: selectUserId,
sortComparer: false
});
export const initialState = adapter.getInitialState({error: null,selectedPostId: null});
const testsReducer = createReducer(
initialState,
on(postActions.loadPostsSuccess, (state, {posts}) => adapter.setAll(posts, state)),
on(postActions.loadPostsFailed, (state, {error}) => ({...state, error})),
on(postActions.setSelectedPostId, (state, {id}) => ({...state, selectedPostId: id}))
);
export function reducer(state: PostState, action: Action) {
return testsReducer(state, action);
}
// Selectors
const {
selectIds,
selectEntities,
selectAll,
selectTotal,
} = adapter.getSelectors();
const feature = createFeatureSelector<PostState>('posts');
export const getPosts = createSelector(feature,selectAll);
export const getSelectedPostId = (state: PostState) => state.selectedPostId;
export const selectPostId = createSelector(
feature,
getSelectedPostId
);
export const selectPostById = (id: string) => createSelector(
selectEntities,
entities => entities[id]
);
您必须 link 适配器中的 selectEntities
选择器到 feature
一个(由 createFeatureSelector
函数创建),然后使用它来获取所需的实体编号.
您可以尝试以下方法:
// Selectors
const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors();
const feature = createFeatureSelector<PostState>('posts');
// ...
// Create a selector from the feature selector and selectEntities one.
export const selectPostEntities = createSelector(feature, selectEntities);
// Use the new selector `selectPostEntities` to slice the post entity from it.
export const selectPostById = (id: number) =>
createSelector(selectPostEntities, (entities) => entities[id]);
此外,您可以通过仅使用 asyn
管道订阅 selectedPost
observable 来优化您的组件模板,如下所示:
<ng-container *ngIf="selectedPost | async as _selectedPost">
<!-- You can now use the `_selectedPost` variable without `async` pipe for all the elements inside the ng-container -->
</ng-container>
我有一个博客应用程序,我正在使用 ngrx。
应用程序 - 现在 - 在商店中有两个对象
{
"posts": [...],
"users": [...]
}
现在我想制作一个单独的组件来显示单个 post (selected-post.component).
我尝试 select 使用实体的 ID select 或者像这样:
export const selectPostById = (id: string) => createSelector(
selectEntities,
entities => entities[id]
);
然后在组件中获取:
postId: string = localStorage.getItem("_selectedPostId");
selectedPost: Observable<Post> = this.store.select(selectPostById(postId));
然后在我使用的视图中显示它:
<ng-container *ngIf="selectedPost | async">
<div class="post text-light">
<div class="p-title fs-3">{{(selectedPost | async).title}}</div>
<div class="p-image">
<img [src]="(selectedPost | async).imageSrc">
</div>
<div class="p-cont fs-5">
{{(selectedPost | async).content}}
</div>
<div class="p-category float-start fs-6">
<a class="p-1" href="categories/category" *ngFor="let ct of (selectedPost | async).categories">
{{ct}}
</a>
</div>
<div class="p-date float-end fs-6">
{{(selectedPost | async).date}}
</div>
<div class="p-author fs-6">
<a href="users/otheruser">{{(selectedPost | async).author.name}}</a>
</div>
</div>
<div class="info">Comments</div>
<div class="comments text-light">
<div class="comment border rounded m-1" *ngFor="let comment of (selectedPost | async).comments">
<div class="c-author">
<a href="users/otheruser">{{comment.author.name}}</a>
</div>
<div class="c-cont">{{comment.content}}</div>
<div class="-c-date">{{comment.date}}</div>
<div class="replies" *ngIf="comment.replies">
<div class="comment border rounded m-1" *ngFor="let reply of comment.replies">
<div class="c-author">
<a href="users/otheruser">{{reply.author.name}}</a>
</div>
<div class="c-cont">{{reply.content}}</div>
<div class="c-date">{{reply.date}}</div>
</div>
</div>
</div>
</div>
</ng-container>
所以问题是 post 在控制台中没有显示错误:
ERROR TypeError: Cannot read properties of undefined (reading: '1')
我select编辑了ID为“1”的post,它存在于redux devtools显示的状态中。
有什么想法吗?
编辑: 减速器:
import { Action, createFeatureSelector, createReducer, createSelector, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import * as postActions from './actions';
import { Post } from 'src/app/models/post';
export interface PostState extends EntityState<Post> {
error: any;
selectedPostId: string | null;
}
export function selectUserId(a: Post): string {
return a.id;
}
export const adapter: EntityAdapter<Post> = createEntityAdapter<Post>({
selectId: selectUserId,
sortComparer: false
});
export const initialState = adapter.getInitialState({error: null,selectedPostId: null});
const testsReducer = createReducer(
initialState,
on(postActions.loadPostsSuccess, (state, {posts}) => adapter.setAll(posts, state)),
on(postActions.loadPostsFailed, (state, {error}) => ({...state, error})),
on(postActions.setSelectedPostId, (state, {id}) => ({...state, selectedPostId: id}))
);
export function reducer(state: PostState, action: Action) {
return testsReducer(state, action);
}
// Selectors
const {
selectIds,
selectEntities,
selectAll,
selectTotal,
} = adapter.getSelectors();
const feature = createFeatureSelector<PostState>('posts');
export const getPosts = createSelector(feature,selectAll);
export const getSelectedPostId = (state: PostState) => state.selectedPostId;
export const selectPostId = createSelector(
feature,
getSelectedPostId
);
export const selectPostById = (id: string) => createSelector(
selectEntities,
entities => entities[id]
);
您必须 link 适配器中的 selectEntities
选择器到 feature
一个(由 createFeatureSelector
函数创建),然后使用它来获取所需的实体编号.
您可以尝试以下方法:
// Selectors
const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors();
const feature = createFeatureSelector<PostState>('posts');
// ...
// Create a selector from the feature selector and selectEntities one.
export const selectPostEntities = createSelector(feature, selectEntities);
// Use the new selector `selectPostEntities` to slice the post entity from it.
export const selectPostById = (id: number) =>
createSelector(selectPostEntities, (entities) => entities[id]);
此外,您可以通过仅使用 asyn
管道订阅 selectedPost
observable 来优化您的组件模板,如下所示:
<ng-container *ngIf="selectedPost | async as _selectedPost">
<!-- You can now use the `_selectedPost` variable without `async` pipe for all the elements inside the ng-container -->
</ng-container>