NX + NGRX TypeError: объекты не повторяются. Зачем? - PullRequest
0 голосов
/ 12 июля 2020

Я использовал Ngrx в прошлом, и у меня не было проблем. Теперь я пытаюсь использовать Entities в первый раз, и это вообще не работает.

У меня есть приложение Angular9 + в рабочем пространстве NX, которое вызывает некоторые фиктивные данные из службы.

Кто-нибудь скажет мне что случилось? Я не могу разобраться. (это длинный пост)

Файл действий:

....
export const loadSheetData = createAction('[SheetData] Load SheetData');

export const loadSheetDataSuccess = createAction(
  '[SheetData] Load SheetData Success',
  props<{ sheetData: SheetDataEntity[] }>()
);
....

Файл эффектов

....
@Injectable()
export class SheetDataEffects {
  loadSheetData$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SheetDataActions.loadSheetData),
      fetch({
        run: (action) => {
          return this.bottomSheetSvc.getSheetData().pipe(
            tap((obj) => 
            catchError(error => of(new Error('Effect failed') ) ),
            map((data) => SheetDataActions.loadSheetDataSuccess({ sheetData: data}) ) );

        onError: (action, error) => {
          return SheetDataActions.loadSheetDataFailure({ error });
        },
      })
    )
  );
....

Файл модели

export interface SheetDataEntity {
  id: string | number; // Primary ID
  info: string;
  link: string;
  icon?: string; 
  isDisabled?: boolean;
}

Файл редуктора

export const SHEETDATA_FEATURE_KEY = 'sheetData';

export interface State extends EntityState<SheetDataEntity> {
  selectedId?: string | number; // which SheetData record has been selected
  loaded: boolean; // has the SheetData list been loaded
  error?: string | null; // last none error (if any)
}

export interface SheetDataPartialState {
  readonly [SHEETDATA_FEATURE_KEY]: State;
}

export const sheetDataAdapter: EntityAdapter<SheetDataEntity> = createEntityAdapter<
  SheetDataEntity
>();

export const initialState: State = sheetDataAdapter.getInitialState({
  // set initial required properties
  entities: {
    0: {}
  },
  loaded: false,
});

const sheetDataReducer = createReducer(
  initialState,
  on(SheetDataActions.loadSheetData, (state) => ({
    ...state,
    loaded: false,
    error: null,
  })),
  on(SheetDataActions.loadSheetDataSuccess, (state, { sheetData }) => 
  {
    console.log('TEMP1:', state, sheetData);
    let temp = sheetDataAdapter.setAll(sheetData, { ...state, loaded: true })
    console.log('TEMP2:', temp);
    return temp;
  }
    
  ),
  on(SheetDataActions.loadSheetDataFailure, (state, { error }) => ({
    ...state,
    error,
  }))
);

export function reducer(state: State | undefined, action: Action) {
  console.log('SHEET REDUCER::', state, action);
  return sheetDataReducer(state, action);
}

Файл селекторов

....
export const getAllSheetData = createSelector(
  getSheetDataState,
  (state: State) => selectAll(state)
);
....

Сервисные данные

dummyData: any = {
    ids: [5, 4, 3, 2, 1],
    entities: {
      1: {
        id: 1,
        info: 'test info 1',
        link: '/test1',
        icon: 'test icon 1', 
        isDisabled: false
      },
      2: {
        id: 2,
        info: 'test info 2',
        link: '/test2',
        icon: 'test icon 2', 
        isDisabled: false
      },
      3: {
        id: 3,
        info: 'test info 3',
        link: '/test3',
        icon: 'test icon 3', 
        isDisabled: false
      },
      4: {
        id: 4,
        info: 'test info 4',
        link: '/test4',
        icon: 'test icon 4', 
        isDisabled: false
      },
      5: {
        id: 5,
        info: 'test info 5',
        link: '/test5',
        icon: 'test icon 5', 
        isDisabled: false
      }
    }

  };

Файл компонента

sheetData$: Observable<SheetDataEntity[]>;

constructor(
    private store: Store<State>,
    ) {

      this.sheetData$ = this.store.pipe( select( selectors.getAllSheetData ) );
    }

  ngOnInit(): void {
    this.store.dispatch( actions.loadSheetData() );
  }

Файл шаблона

<sheet-item 
        *ngFor="let item of (sheetData$ | async)" 
        [item]="item" 
        (onUpdateSelectedLink)="updateSelectedLink($emit)">
    </sheet-item>

1 Ответ

0 голосов
/ 14 июля 2020

Ура! наконец успех. Тупая ошибка! Я изменил фиктивные данные службы, чтобы они были обычным массивом элементов. Затем передал это в «успешное действие». Запутался, пытаясь следовать нескольким руководствам, использующим разные Angular версии и стили кода. Спасибо @derekkite / @RoboZoom (в Gitter), вы наставили меня на правильный путь. :)

run: (action) => {
          return this.bottomSheetSvc.getSheetData().pipe(
            tap((obj) => console.log('Effect: switch:', obj)),
            catchError(error => of(new Error('Effect failed') ) ),
            map((dataObj) => SheetDataActions.loadSheetDataSuccess({ sheetData: dataObj.data }) ) );
        },
    
...