The NgRX Effect is malfunctioning

Working on integrating ngrx with Angular. Authentication is successful, but facing issues with product store implementation:

Organizing the project using modules:

const routes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
  },
  {
    path: 'home',
    loadChildren: () => import('src/app/home/home.module')
      .then(module => module.HomeModule)
  }
]

@NgModule({
  declarations: [
    AppComponent
  ],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        RouterModule.forRoot(routes),
        EffectsModule.forRoot([]),
        StoreModule.forRoot({}),
        StoreDevtoolsModule.instrument({
            maxAge: 25,
            logOnly: environment.production
        }),
        TopBarModule,
        AuthModule,
        HomeModule

    ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Injecting effect services in the home module:

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  }
]
@NgModule({
  declarations: [
    HomeComponent
  ],
  imports: [
    CommonModule,
    RouterModule.forChild(routes),
    EffectsModule.forFeature([
      GetCategoryEffectsService,
      GetProductEffectService
    ]),
    StoreModule.forFeature('category', categoryReducers),
    StoreModule.forFeature('product', productReducers),
  ],
  providers: [
    GetCategoriesService,
    GetProductsService
  ]
})
export class HomeModule { }

The redux setup seems correct but the effect is not functioning properly:

@Injectable()
export class GetProductEffectService {

  constructor(
    private actions$: Actions,
    private getProductsService: GetProductsService
  ) { }

  getProducts$ = createEffect( () =>
    this.actions$.pipe(
      ofType(getProductAction),
      switchMap(() => {
        return this.getProductsService.getProducts().pipe(
          map((products) => getProductActionSuccess({products}))
        )
      })
    ))
}

If subscribing to the method directly without store, all products are fetched...

Defined actions:

export const getProductAction = createAction(
  ProductActionTypes.PRODUCT_ACTION
);

export const getProductActionSuccess = createAction(
  ProductActionTypes.PRODUCT_ACTION_SUCCESS,
  props<{products: ProductInterface[]}>()
);

export const getProductActionFailure = createAction(
  ProductActionTypes.PRODUCT_ACTION_FAILURE,
  props<{error: BackendErrorsInterface}>()
);

export enum ProductActionTypes {
  PRODUCT_ACTION = '[Product] product action',
  PRODUCT_ACTION_SUCCESS = '[Product] product action success',
  PRODUCT_ACTION_FAILURE = '[Product] product action failure',
}
The reducers for product state are structured similarly to other working reducers:

const initialState: ProductStateInterface = {
  data: null,
  error: null,
  isLoading: false,
  isSubmitting: false
}

const reducers = createReducer(
  initialState,
  on(
    getProductAction,
    (state): ProductStateInterface => ({
      ...state,
      isLoading: true,
      error: null
    })
  ),

  on(
    getProductActionSuccess,
    (state, action): ProductStateInterface => ({
      ...state,
      data: action.products,
      isLoading: false,
      error: null
    })
  ),

  on(
    getProductActionFailure,
    (state, action): ProductStateInterface => ({
      ...state,
      data: null,
      isLoading: false,
      error: action.error
    })
  )
);
export function productReducers(state: ProductStateInterface, action: Action){
  return reducers(state, action);
}

Selecting actions in product selector file:

export const actionFeatureSelector = createFeatureSelector<
  AppStateInterface,ProductStateInterface>('product');

export const productIsLoadingSelector = createSelector(
  actionFeatureSelector,
  (productState: ProductStateInterface) => productState.isLoading
);

export const getProductsSelector = createSelector(
  actionFeatureSelector,
  (productState: ProductStateInterface) => productState.data
);

export const productErrorSelector = createSelector(
  actionFeatureSelector,
  (productState: ProductStateInterface) => productState.error
);

export const productIsSubmittingSelector = createSelector(
  actionFeatureSelector,
  (productState: ProductStateInterface) => productState.isSubmitting
);

No update is observed in the store. Below is the component logic:

ngOnInit(): void {
    this.initializeValues();
  }

  private initializeValues(): void {
  
    this.store.pipe(select(getProductsSelector)) //.subscribe(test => console.log(test));
   
    this.categories$ = this.store.pipe(select(categorySelector));
    
    this.isLoading$ = this.store.pipe(select(isLoadingSelector));
  }

Answer №1

When getProductAction is dispatched, an effect is triggered. Here's the code:

getProducts$ = createEffect( () =>
    this.actions$.pipe(
      ofType(getProductAction),
      switchMap(() => {
        return this.getProductsService.getProducts().pipe(
          map((products) => getProductActionSuccess({products}))
        )
      })
    ))

However, the action is never dispatched in your component, meaning the effect is never triggered.

To fix this, make sure to dispatch the action in your component:

ngOnInit(): void {
    this.initializeValues();
    this.store.dispatch(getProductAction()); // <-- trigger the effect to fetch the products

  }

  private initializeValues(): void {
  
    this.store.pipe(select(getProductsSelector))
   
    this.categories$ = this.store.pipe(select(categorySelector));
    
    this.isLoading$ = this.store.pipe(select(isLoadingSelector));
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can someone assist me with running queries on the MongoDB collection using Node.js?

In my mongodb collection called "jobs," I have a document format that needs to display all documents matching my query. { "_id": { "$oid": "60a79952e8728be1609f3651" }, "title": "Full Stack Java Develo ...

Preventing me from instantiating objects

I've been struggling with an issue for a while now consider the following: export abstract class abstractClass { abstract thing(): string } export class c1 extends abstractClass { thing(): string { return "hello" } } export cla ...

The ArgsTable component is not displayed in Storybook when using Vite, Typescript, and MDX

I'm struggling to display the table with props on a MDX documentation page. No matter what I try, the table only shows: "No inputs found for this component. Read the docs >" Despite trying various methods, I can't seem to get it to work. I h ...

Understanding the basics of reading a JSON object in TypeScript

Displayed below is a basic JSON structure: { "carousel": [], "column-headers": [{ "header": "Heading", "text": "Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id el ...

Utilize Function type while preserving generics

Is there a way in Typescript to reference a function type with generics without instantiating them, but rather passing them to be instantiated when the function is called? For instance, consider the following type: type FetchPageData<T> = (client : ...

Having difficulty handling the "of" class within the "rxjs" framework

I have created a custom class named ValueService. Here is the code snippet: import { Injectable } from '@angular/core'; import { of } from 'rxjs'; import { delay } from 'rxjs/operators'; @Injectable() export class ValueSer ...

Implementing Styled API in TypeScript with props: A Comprehensive Guide

I'm currently working on styling a component using the new styled API, not to be confused with StyleComponents. const FixedWidthCell = styled(TableCell)((props: { width: number }) => ({ width: props.width || 20, textAlign: "center", })) The i ...

Troubles encountered while attempting to properly mock a module in Jest

I've been experimenting with mocking a module, specifically S3 from aws-sdk. The approach that seemed to work for me was as follows: jest.mock('aws-sdk', () => { return { S3: () => ({ putObject: jest.fn() }) }; }); ...

NGXS: Issue with passing objects to "setState" occurs when any of the patched inner fields is nullable or undefined

In my Angular components, I have created a class that is responsible for storing the state: export class MyStateModel { subState1: SubStateModel1; substate2: SubStateModel2; } This class has simple subclasses: export class SubStateModel1 { someField ...

A simple way to retrieve data from Firebase using the unique identifier (ID)

Hello, I am attempting to retrieve the user email for each message. Each message (chat) has a user ID associated with it. I fetch the entire user data using getUser on the *ngIf directive and then display the email address. It works fine and there are no ...

Issue with Adding Additional Property to react-leaflet Marker Component in TypeScript

I'm attempting to include an extra property count in the Marker component provided by react-leaflet. Unfortunately, we're encountering an error. Type '{ children: Element; position: [number, number]; key: number; count: number; }' is n ...

The ng command seems to be malfunctioning when executed from a separate directory

After selecting a different folder for my new angular project, I encountered an error every time I tried to run an ng command: 'ng' is not recognized as an internal or external command, operable program or batch file. I attempted to resolve ...

Is the function signature defined by this Interface syntax?

While exploring some code, I came across the following: export interface SomeInterface<T> { <R>(paths: string[]): Observable<R>; <R>(Fn: (state: T) => R): Observable<R>; } After searching through the TypeScript do ...

Challenge with React CloneElement regarding typing

Utilizing React Children and React Clone element, I aim to trigger methods in both the wrapper and Select components upon onClick event in the Option component. Although everything is functioning correctly, I am encountering a type error when calling the O ...

Managing loading and changing events using Angular, jQuery, and Web API

I am populating a dropdown select using ng-repeat. <select onchange="ChangeMonth()" id="month"> <option ng-repeat="(key,val) in Months" ng-selected="val==ActiveMonth" value="{{key}}"> {{val}} ...

React Hook Form is flagging missing dependencies in the useEffect function

Before posting this question, I made an effort to search for a solution on Google. However, I am puzzled by the warning that the linter is giving me regarding my code. The warning message reads: ./components/blocks/Contact.tsx 119:6 Warning: React Hook us ...

Is it possible to retrieve and utilize multiple Enum values in Typescript?

Combine enum values to retrieve corresponding enum strings. Consider the following scenario: enum EnumDays { NONE = 0, SUN = 1, MON = 2, TUE = 4, WED = 8, THU = 16, FRI = 32, SAT = 64, ALL = 127 } If I pass a value o ...

Ensuring TypeORM constraint validations work seamlessly with MySQL and MariaDB

I recently started using TypeORM and I'm trying to incorporate the check decorator in my MySQL/MariaDB database. However, after doing some research on the documentation and online, it seems that the check decorator is not supported for MySQL. I'v ...

To ensure the next line only runs after the line above has finished executing, remember that the function is invoked in HTML

my.component.html <button (click)="refresh()">Refresh</button> my.component.ts refresh() { let self = this; self.isRefresh = true; //1st time self.getfun().then(() => { self.isRefresh = false; ...

Preventing page reload when altering parameters in Angular 9

I have recently utilized Angular9 along with PathLocationStrategy {provide: LocationStrategy, useClass: PathLocationStrategy}, The issue I am facing is: Whenever I use form.submit() to send data to the backend, the backend then redirects back to the c ...