Home > Net >  NGRX effect not storing correct data
NGRX effect not storing correct data

Time:11-21

I am currently using NGRX Effect to fetch some random data from JSONPlaceHolder Typicode API. I have written some Actions and also the reducers. The effect runs well and also I get the expected data in my reducer... But it does not show up in the store.

UserActions.ts

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

export const FetchUsersRequest = createAction('[USERS] FETCH REQUEST');
export const FetchUsersSuccess = createAction(
  '[USER] FETCH SUCCESS',
  props<{ data: Array<any> }>()
);
export const FetchUsersFail = createAction(
  '[USER] FETCH SUCCESS',
  props<{ error: string }>()
);

UserReducer.ts

import { state } from '@angular/animations';
import { createReducer, on } from '@ngrx/store';
import * as UserActions from './User.actions';
import { UserService } from './user.service';

interface State {
  loading: boolean;
  error: string | null;
  users: Array<any>;
}

export const initialState: State = {
  loading: false,
  error: '',
  users: [],
};

export const userReducer = createReducer(
  initialState,
  on(UserActions.FetchUsersRequest, (state) => ({ ...state, loading: true })),
  on(UserActions.FetchUsersSuccess, (state, { data }) => {
    return { ...state, users: [...state.users, ...data] };
  }),
  on(UserActions.FetchUsersFail, (state, { error }) => ({
    ...state,
    loading: false,
    users: [],
    error,
  }))
);

UserService.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export class UserService {
  constructor(private http: HttpClient) {}

  getUsers() {
    return this.http.get('https://jsonplaceholder.typicode.com/users');
  }
}

UserEffect.ts

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import * as UserActions from './User.actions';
import { map, exhaustMap } from 'rxjs/operators';
import { UserService } from './user.service';

@Injectable()
export class UserEffects {
  constructor(private actions$: Actions, private userService: UserService) {}

  userFetch$ = createEffect(() =>
    this.actions$.pipe(
      ofType(UserActions.FetchUsersRequest),
      exhaustMap((action) =>
        this.userService.getUsers().pipe(
          map((response: any) => {
            console.log(response);
            return UserActions.FetchUsersSuccess({ data: response });
          })
        )
      )
    )
  );

}

App.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

import { StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { EffectsModule } from '@ngrx/effects';
import { UserEffects } from './User/Users.effects';
import { userReducer } from './User/User.reducer';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    EffectsModule.forRoot([UserEffects]),
    StoreModule.forRoot({
      users: userReducer
    }),
    StoreDevtoolsModule.instrument({
      maxAge: 50,
    }),
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

In App component I call a method on Button Click, that invokes the user fetch effect.

App.component.ts

import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import * as UserActions from './User/User.actions';


interface AppState {
  users: any;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  title = 'ngrxtest';

  users$: Observable<any>;

  constructor(private store: Store<AppState>) {
    this.users$ = this.store.select('users');
  }


  fetchUsers() {
    this.store.dispatch(UserActions.FetchUsersRequest());
  }
}

User Fetch Request State

User Fetch Success State

CodePudding user response:

Since you have same Action type for both success and Failure. It might reset data inside reducer try to rename failure action type

export const FetchUsersSuccess = createAction(
  '[USER] FETCH SUCCESS',
  props<{ data: Array<any> }>()
);
export const FetchUsersFail = createAction(
  '[USER] FETCH FAILURE',
  props<{ error: string }>()
);
  • Related