Search code examples
angularreduxngrx

trying to save an array to ngrx state


I'm trying to save an array I get from an api calling, using ngrx effects, then simply *ngfor that array. I'm trying to use ngrx but its making things more complicated. I am passing an array into the reducer but the state.comics is showing like this comics: [0: {0: {..}, 1:{..}], when all I want it to be is like comics: [0: {..}, 1: {..}]j. So the reducer is not saving the array to the comics, its pushing to the 0 then creating more objects.

comics.data.results is an Array

action:

import { createAction, props } from '@ngrx/store';

export const getComics = createAction('[Comics] Get comics');
export const getComicsSuccess = createAction(
  '[Comics] Success Get Comics',
  (comics: any) => comics
);

effects.ts

@Injectable()
export class ComicEffects {
  loadComics$ = createEffect(() =>
    this.action$.pipe(
      ofType(getComics),
      exhaustMap(() =>
        this.dataService.getComics().pipe(
          map((comics) => {
            console.log(comics.data.results);
            return getComicsSuccess(comics.data.results);
          })
          /* catchError(() => EmptyError) */
        )
      )
    )
  );

  constructor(
    private action$: Actions,
    private dataService: MarvelServiceService
  ) {}
}

Reducer:

import { createReducer, on } from '@ngrx/store';
import { getComicsSuccess } from '../Actions/comics.action';

const initialState: any = [];

export const comicReducer = createReducer(
  initialState,
  on(getComicsSuccess, (state, data) => [...state, data])
);

html:

<ul>
  <li *ngFor="let comic of comics$ | async; index as i">
    {{ i + 1 }}
  </li>
</ul>

component:

export class ComicsComponent implements OnInit {
  comics$ = this.store.select((state) => state.comics);

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

  ngOnInit() {
    this.getAllComics();
  }

  getAllComics() {
    this.store.dispatch(getComics());

  }
}

app.module:

 StoreModule.forRoot({ comics: comicReducer }),

Solution

  • I would guess that comics.data.results is also an array.

    so if you need to save it in state you need to use spread operator on it too. so it all can be one single array.

    // Action
    import { createAction, props } from '@ngrx/store';
    
    export const getComicsSuccess = createAction('[Comics] Success Get Comics', props<{ comics: any[] }>());
    
    // Effect
    this.dataService.getComics().pipe(
      map((getComics: any) => {
        return getComicsSuccess({ comics: getComics.data.results });
      })
    );
    
    //Reducer
    export const comicReducer = createReducer(
      initialState,
      on(getComicsSuccess, (state, {comics}) => [...state, ...comics])
    );