What is the Purpose of Including the Reducer Name in the NGRX State Tree?

I've encountered an issue while using NGRX to store a simple object. When the object is added to the state tree, the reducer's name is also included, causing problems when I try to strongly type my selector and subscribe to it.

Here is the code snippet:

Reducer:

  export interface State extends AppState.State {
   player: PlayerState;
  }

 export interface PlayerState {
  currentSkick: ISkick;
  }

 export const initialState: PlayerState = {
 currentSkick: null,
 };

 export const reducer = createReducer<PlayerState>(
  initialState,
  on(
   PlayerActions.setCurrentSkick,
   (state, action): PlayerState => {
    return {
     ...state,
     currentSkick: action.skick,
    };
   }
  )
 );

Selector:

const getCurrentSkickFeaturesState = createFeatureSelector<PlayerState >(
 'player'
);

export const getCurrentSkick = createSelector(
   getCurrentSkickFeaturesState,
   (state) => state.currentSkick
 );

Actions:

export const setCurrentSkick = createAction(
  '[Player] Set Current Skick',
   props<{ skick: ISkick }>()
 );

Feature Module:

@NgModule({

 imports: [
   StoreModule.forFeature('player', { reducer }),
  ],
})
export class SkickPlayerModule {}

App Module:

@NgModule({
declarations: [AppComponent ],
imports: [
BrowserAnimationsModule,
StoreModule.forRoot({}, {}),
StoreDevtoolsModule.instrument({
name: 'player',
maxAge:25,
logOnly: environment.production
})],
})
export class AppModule {}

Skick Interface:

export interface ISkick {
  fileVersion: string;
  formatVersion: string;
   title: string;
   author: string;
   authorEmail: string;
   creationDate: Date;
   uniqueId: string;
   thumbnailLink: string;
   frames: Frame[];
    assets: Assets;
 }

and The Component:

  //Dispatch the action set the current object
  async loadSkick(zip: JSZip) {
    let skickPlayer = await this.getFileToText(zip);  
    this.store.dispatch(PlayerActions.setCurrentSkick({ skick: skickPlayer }));
  }

 ngOnInit(): void {   

 //Subscribe to get the current object
  this.store.select(getCurrentSkick).subscribe((skick) => {
       this.skickPlayer = skick;
     if (this.skickPlayer) this.performFrame(0);
  });

  }

The problem arises because NGRX is appending the name of the reducer to the tree, as shown in this image: https://i.sstatic.net/8jjQz.png

Any insights on why accessing the object from the subscription fails due to this "reducer" naming convention in the tree? Ideally, the object structure in the tree should be Player.currentSkick instead of player.reducer.currentSkick

Answer №1

When importing the reducer in your modules, it is important to do so correctly. Instead of importing with '*' as in the example below:

import * as fromMyFeature from 'somewhere.reducer';

You should specify the import in this manner:

@NgModule({

 imports: [
  StoreModule.forFeature('player', fromMyFeature.reducerExportName),
 ],
})
export class SkickPlayerModule {}

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

Discovering the index of an item in Angular

My delete function emits socket.io to update the other party's items list and remove the specific item. The issue arises when I receive the socket data as I struggle to find the matching item to update it. Logic User 1 deletes a message User 2 receiv ...

Conflicting Angular controller names within different modules

I'm facing an issue where two modules (A and B) with controllers of the same name are conflicting when imported into module C. Is there a recommended solution to prevent this conflict, such as using a naming convention like "module.controller" for ea ...

p-menu fails to appear

I'm currently experimenting with Primeng and Angular 2 to put together a basic menu. Take a look at my code snippet: import {Component, OnInit} from '@angular/core'; import {Menu, MenuItem} from 'primeng/primeng'; @Component({ ...

A guide on transferring data between two arrays of objects using TypeScript

I am working on implementing a get request within a component that retrieves a response: getPaymentIntents(): Observable<Payment>{ const url: string = 'https://store.com//payments'; return this.http.get<Payment>(url); } ...

What is the method for adding an item to an array in JavaScript?

actions = [{ 'name' : 'Share', 'icon' : 'fa fa-share-alt library_icon mylibrary-icon-right' },{ 'name' : 'Edit', 'icon' : 'fa fa-pencil-square-o library_icon mylibrary ...

Expand or reduce the displayed content based on the preset value in Angular

I am trying to implement a "Show More" and "Show Less" functionality for a product's description. It works fine with normal strings, but when I try to apply the same logic to the value with {{product.description}}, the entire value inside {{product.de ...

Can TypeScript be used to dynamically render elements with props?

After extensive research on SO and the wider web, I'm struggling to find a solution. I have devised two components, Link and Button. In short, these act as wrappers for <a> and <button> elements with additional features like chevrons on t ...

Angular is failing to transfer control to the Web API

I'm currently utilizing a SQLite database and attempting to insert a record into the 'Departments' table. Below is the code snippet from my Web API controller: [HttpPost] public async Task<ActionResult> SaveDept(CreateDepartmentDto de ...

Angular FormData fails to append and upload files

I am attempting to use FormData in order to upload a file through an HTTP Request. Here is the HTML code: <ng-template #displayApp> <div class="display flex justify-content-center"> <div > <p-fileUploa ...

NavigatedRoute and Auth-protect - problem retrieving ID from paramMap

Currently working on a website for my exam project, but encountering an issue with the AuthGuard not returning the correct ID in my code. event-details.component.ts getEvent(): void { const id = +this.route.snapshot.paramMap.get('id'); ...

The power of Ionic 2 combined with the Web Audio API

I am currently developing an Ionic 2 application that requires access to the user's microphone. When working on a web platform, I would typically use the following code snippet to obtain microphone access. navigator.getUserMedia = (navigator['ge ...

How to create an array of objects in TypeScript

I am looking to define an array of objects in TypeScript. Here is my example: const a = [{ name: 1, age: 2, car1: 8, car2: 8, car3: 8, name4: 1, age4: 2, car41: 8, car42: 8, car34: 8, }, { name: 1, age: 2, car1: 8, car2: 8, ...

Ways to expose a declared module in Enzyme's shallow rendering?

I've been grappling with how to ensure that my custom declared module is detected when I shallow render a component using enzyme in Jest unit tests. The issue revolves around a specific module declaration named _aphrodite, which looks like this: // i ...

Error: Unable to find provider for Store in Angular 9 AuthService Guard

I have been working on implementing an Auth guard with Angular 9, but I encountered an ERROR in the browser console: ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(SampleModule)[AuthGuard -> Store -> Store -> Store -& ...

Encountered a PrismaClientValidationError in NextJS 13 when making a request

I am currently working on a school project using NextJS 13 and attempting to establish a connection to a MYSQL database using Prisma with PlanetScale. However, when trying to register a user, I encounter the following error: Request error PrismaClientValid ...

The Nestje subscription is encountering a NULL value and displaying an error message stating: "Non-nullable field Subscription cannot be returned as null."

I attempted to implement a Subscription in my nestjs project with GraphQL, but encountered the following error message: Cannot return null for non-nullable field Subscription Below is the code snippet: //* ~~~~~~~~~~~~~~~~~~~ Subscription ~~~~~~~~~~~ ...

Accessing S3 bucket contents in Angular using Observables

Looking for guidance on structuring a service method in Angular4 to create an s3.listObjects call and return the contents of an S3 bucket as an Observable. Here is my current attempt, unfortunately not yielding successful results: public retrieveFilesFro ...

A method for handling specific subsets of an enum in a secure and controlled manner

I have an enumerated type called Country and another type that represents a subset of European countries. I want to handle values within this subset differently from others. Currently, I am using an if statement with multiple conditions, but it could get u ...

Tips for Modifying the currentUrl identifier in Angular 2

I am trying to change the ID property of my currentUrl object within my component. My goal is for the ID to update and then fetch the corresponding data based on that ID. However, I keep encountering this error message: "Cannot assign to read only propert ...

Tips for closing Angular Material Sidenav using the escape key

I am attempting to automatically close the Angular Material Sidenav by pressing the escape key. Despite my efforts to use the [autoFocus]="true" property, I have not been successful in achieving this functionality. The issue lies in the fact that pressin ...