簡體   English   中英

無法讀取未定義(讀取“地圖”)NGRX 實體的屬性

[英]Cannot read properties of undefined (reading 'map') NGRX Entity

它發生在 selectAll 選擇器上,我查看了其他答案,我正在使用 createfeatureSelector 來調用 state。 我已經設法調度操作,將 state 保存到商店,但我不能使用選擇器。 任何幫助將不勝感激。

ERROR TypeError: Cannot read properties of undefined (reading 'map')
    at ngrx-entity.mjs:21
    at ngrx-store.mjs:697
    at memoized (ngrx-store.mjs:578)
    at defaultStateFn (ngrx-store.mjs:601)
    at ngrx-store.mjs:700
    at memoized (ngrx-store.mjs:578)
    at ngrx-store.mjs:697
    at memoized (ngrx-store.mjs:578)
    at defaultStateFn (ngrx-store.mjs:601)
    at ngrx-store.mjs:700

todos.actions.ts

import { Update } from "@ngrx/entity";
import { createAction, props } from "@ngrx/store";
import { Todo } from "../../../models/todo.interface";

export enum TodosActionTypes {
  GET_TODOS = '[todos] get todos',
  GET_TODOS_FAIL = '[todos] get todos fail',
  GET_TODOS_SUCCESS = '[todos] get todos success',
  ADD_TODO = '[todo] add todo',
  EDIT_TODO = '[todo] edit todo',
  DELETE_TODO = '[todo] delete todo',
}

const getTodos = createAction(TodosActionTypes.GET_TODOS);
const getTodosFail = createAction(TodosActionTypes.GET_TODOS_FAIL, props<{error: Error}>());
const getTodosSuccess = createAction(TodosActionTypes.GET_TODOS_SUCCESS, props<{todos: Todo[]}>());
const editTodo = createAction(TodosActionTypes.EDIT_TODO, props<{edit: Update<Todo>, completed: boolean}>());
const deleteTodo = createAction(TodosActionTypes.DELETE_TODO, props<{id: string}>());
const addTodo = createAction(TodosActionTypes.ADD_TODO, props<{todo: Todo}>());

export const TodosActions = {
  getTodos,
  getTodosFail,
  getTodosSuccess,
  editTodo,
  deleteTodo,
  addTodo
};

todos.reducer.ts

import { createEntityAdapter, EntityAdapter, Update } from '@ngrx/entity';
import { createReducer, on } from '@ngrx/store';
import { Todo } from '../../../models/todo.interface';
import { TodosState } from '../../../models/todos-state.interface';
import { TodosActions } from '../actions/todos.actions';

export function selectTodoId(a: Todo): string {
  return a.id;
}
export function sortByName(a: Todo, b: Todo): number {
  return a.name.localeCompare(b.name);
}
export const adapter: EntityAdapter<Todo> = createEntityAdapter<Todo>({
  selectId: selectTodoId,
  sortComparer: sortByName,
});

export const initalState: TodosState = adapter.getInitialState({
  loading: false,
  loaded: false,
  error: {
    message: '',
    name: '',
  },
});

function getTodosHandler(state = initalState) {
  return {
    ...state,
    loading: true,
  };
}
function getTodosFailHandler(state = initalState, action: { error: Error }) {
  return {
    ...state,
    loading: false,
    loaded: true,
    error: action.error,
  };
}

function getTodosSuccessHandler(
  state = initalState,
  action: { todos: Todo[] }
) {
  return adapter.addMany(action.todos, {
    ...state,
    loading: false,
    loaded: true,
  });
}
function editTodosHandler(state = initalState, action: { edit: Update<Todo> }) {
  return adapter.updateOne(action.edit, {
    ...state,
  });
}
function deleteTodoHandler(state = initalState, action: { id: string }) {
  return adapter.removeOne(action.id, {
    ...state,
  });
}
function addTodoHandler(state = initalState, action: {todo: Todo}) {
  return adapter.addOne(action.todo, {
    ...state,
  })
}
export const TodosReducer = createReducer(
  initalState,
  on(TodosActions.getTodos, getTodosHandler),
  on(TodosActions.getTodosFail, getTodosFailHandler),
  on(TodosActions.getTodosSuccess, getTodosSuccessHandler),
  on(TodosActions.editTodo, editTodosHandler),
  on(TodosActions.deleteTodo, deleteTodoHandler),
  on(TodosActions.addTodo, addTodoHandler)
);

todos.selectors.ts

import { createFeatureSelector, createSelector } from '@ngrx/store';
import { TodosState } from '../../../models/todos-state.interface';
import { adapter } from '../reducers/todos.reducers';
import { Todo } from '../../../models/todo.interface';



const { selectIds, selectEntities, selectAll, selectTotal } =
  adapter.getSelectors();

  export const getTodosFeatureState =
  createFeatureSelector<TodosState>('todos');


const getTodosLoading = (state: TodosState): boolean => state.loading;
const getTodosLoaded = (state: TodosState): boolean => state.loaded;

const selectAllTodos = createSelector(getTodosFeatureState, selectAll);


const selectCompletedTodos = createSelector(selectAllTodos, (todos: Todo[]) => todos.filter(todo => todo.completed === true));

const selectTodosLoading = createSelector(getTodosFeatureState, getTodosLoading);

const selectTodosLoaded = createSelector(getTodosFeatureState, getTodosLoaded);

const selectAllTodosIds = createSelector(getTodosFeatureState, selectIds);

const selectAllTodosEntities = createSelector(getTodosFeatureState, selectEntities);

const selectTodosTotal = createSelector(getTodosFeatureState, selectTotal);

export const TodosSelectors = {
  selectAllTodos,
  selectCompletedTodos,
  selectTodosLoading,
  selectTodosLoaded,
  selectAllTodosIds,
  selectAllTodosEntities,
  selectTodosTotal
}

todos-index.reducer.ts

import { ActionReducerMap } from '@ngrx/store';
import { TodosState } from '../../../models/todos-state.interface';
import * as fromTodosReducer from './todos.reducers';


export interface TodosFeatureState {
  todos: TodosState;
}

export const reducers: ActionReducerMap<TodosFeatureState> = {
  todos: fromTodosReducer.TodosReducer,
};

todos.effect.ts

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { catchError, map, switchMap, take, } from 'rxjs';
import { Todo } from '../../../models/todo.interface';
import { TodosService } from '../../../services/todos.service';
import { TodosActions, TodosActionTypes } from '../actions/todos.actions';

@Injectable()
export class TodosEffects {
  constructor(private todosService: TodosService, private actions$: Actions) {}
  loadTodos$ = createEffect(() =>
    this.actions$.pipe(
      ofType(TodosActionTypes.GET_TODOS),
      switchMap(() =>
        this.todosService.getTodos().pipe(
          take(1),
          map((todos: Todo[]) => TodosActions.getTodosSuccess({ todos })),
          catchError(async (error: Error) =>
            TodosActions.getTodosFail({ error })
          )
        )
      )
    )
  );

}

todos狀態模塊

import { NgModule } from "@angular/core";
import { EffectsModule } from "@ngrx/effects";
import { StoreModule } from "@ngrx/store";
import { SnackBarService } from "../../services/snackbar.service";
import { TodosEffects } from "./effects/todos.effects";
import * as fromTodos from './reducers/todos-index.reducers';

@NgModule({
  imports: [
      StoreModule.forFeature('todos', fromTodos.reducers),
      EffectsModule.forFeature([TodosEffects]),
  ],
  providers:[SnackBarService]
})
export class TodosNgrxStateModule {}

我的 package.json

{
  "name": "marin-software",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "nx",
    "postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main",
    "start": "nx serve",
    "build": "nx build",
    "test": "nx test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~13.1.0",
    "@angular/cdk": "^13.1.1",
    "@angular/common": "~13.1.0",
    "@angular/compiler": "~13.1.0",
    "@angular/core": "~13.1.0",
    "@angular/forms": "~13.1.0",
    "@angular/material": "^13.1.1",
    "@angular/platform-browser": "~13.1.0",
    "@angular/platform-browser-dynamic": "~13.1.0",
    "@angular/router": "~13.1.0",
    "@ngrx/effects": "^13.0.2",
    "@ngrx/entity": "^13.0.2",
    "@ngrx/store": "^13.0.2",
    "@ngrx/store-devtools": "^13.0.2",
    "@nrwl/angular": "13.3.9",
    "@tailwindcss/forms": "^0.4.0",
    "@tailwindcss/typography": "^0.5.0",
    "rxjs": "~7.4.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~13.1.0",
    "@angular-eslint/eslint-plugin": "~13.0.1",
    "@angular-eslint/eslint-plugin-template": "~13.0.1",
    "@angular-eslint/template-parser": "~13.0.1",
    "@angular/cli": "~13.1.0",
    "@angular/compiler-cli": "~13.1.0",
    "@angular/language-service": "~13.1.0",
    "@nrwl/cli": "13.3.9",
    "@nrwl/cypress": "13.3.9",
    "@nrwl/eslint-plugin-nx": "13.3.9",
    "@nrwl/jest": "13.3.9",
    "@nrwl/linter": "13.3.9",
    "@nrwl/nx-cloud": "latest",
    "@nrwl/tao": "13.3.9",
    "@nrwl/workspace": "13.3.9",
    "@types/jest": "27.0.2",
    "@types/node": "14.14.33",
    "@typescript-eslint/eslint-plugin": "~5.3.0",
    "@typescript-eslint/parser": "~5.3.0",
    "cypress": "^9.1.0",
    "eslint": "8.2.0",
    "eslint-config-prettier": "8.1.0",
    "eslint-plugin-cypress": "^2.10.3",
    "jest": "27.2.3",
    "jest-preset-angular": "11.0.0",
    "prettier": "^2.3.1",
    "tailwindcss": "^3.0.7",
    "ts-jest": "27.0.5",
    "typescript": "~4.4.3"
  }
}

嘗試這個

export const getFeatureState =
  createFeatureSelector<TodosState>('todos');
export const getTodosFeatureState =
  createSelector(getFeatureState,state => state.todos);

const selectAllTodos = createSelector(getTodosFeatureState, selectAll);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM