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());
}
}
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 }>()
);