首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ngrx存储-选择一个要在单独模板中显示的实体

ngrx存储-选择一个要在单独模板中显示的实体
EN

Stack Overflow用户
提问于 2022-02-27 18:29:44
回答 1查看 332关注 0票数 2

我有一个博客应用程序,我正在使用ngrx。

应用程序-for现在-在存储中有两个对象

代码语言:javascript
复制
{
"posts": [...],
"users": [...]
}

现在,我想创建一个分离的组件来显示单个post (所选的-post.Component)。

我试图使用这样的选择器通过实体的id来选择该实体:

代码语言:javascript
复制
export const selectPostById = (id: string) => createSelector(
  selectEntities,
  entities => entities[id]
);

然后将其放入组件中:

代码语言:javascript
复制
postId: string = localStorage.getItem("_selectedPostId");

selectedPost: Observable<Post> = this.store.select(selectPostById(postId));

然后,为了在视图中显示它,我使用:

代码语言:javascript
复制
<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')

我选择了id "1“的post,它存在于显示的状态中。

有什么主意吗?

编辑:减速机:

代码语言:javascript
复制
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]
);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-27 19:04:10

您必须将selectEntities选择器从适配器链接到feature one (由createFeatureSelector函数创建),然后使用它通过Id获取所需的实体。

您可以尝试以下方法:

代码语言:javascript
复制
// 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]);

此外,您还可以通过只使用selectedPost管道一次订阅可观察到的asyn来优化组件模板,如下所示:

代码语言:javascript
复制
<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>
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71287456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档