The selectors in NgRx store are failing to retrieve data from the main global store

As I delve into the world of ngrx, I find myself struggling to fully understand and implement it effectively within my application.

Recently, I integrated ngrx version 8.3 into my project in hopes of organizing my state management efficiently.

My goal is to have a structured root state along with separate feature states for each component. However, I encountered an issue where my selector at the root level never seemed to trigger.

Here are the actions defined...

// actions
import { createAction, union } from '@ngrx/store';
import { SecurityTokensState } from './app.reducer';

export const setUrl = createAction(
  '[App url] ',
  (payload: string) => ({ payload })
);

export const setTokens = createAction(
  '[App setSecurityTokens] ',
  (payload: SecurityTokensState) => ({ payload })
);


export const actions = union({
  setUrl,
  setTokens
});

export type ActionsUnion = typeof actions;

And here are the reducers...

import * as rootActions from './app.actions';
import { createReducer, on } from '@ngrx/store';

/** Top level state */
export interface State {
  /** State related to Auth */
  tokens: SecurityTokensState;

  /** General / root app state (eg configuration) */
  app: AppState
}

/** App wide general state */
export interface AppState {
  url: string;
}

/** Security token state */
export interface SecurityTokensState {
  token: string,
  refreshToken: string;
}

const initialState: State = { tokens: undefined, app: { url: ""}  };

export function rootReducer(state: State, action: rootActions.ActionsUnion): State {
  return reducer(state, action);
}

const reducer = createReducer(
  initialState,
  on(rootActions.setTokens,
    (state, { payload }) => ({ ...state, tokens: payload })
  ),
  on(rootActions.setUrl,
    (state, { payload }) => ({ ...state, app: updateUrl(state, payload)}))
)

/** Helper to update the nested url */
const updateUrl = (state: State, payload: string): AppState => {      
  const updatedApp = { ...state.app };
  updatedApp.url = payload;
  return updatedApp;
}

I also created the following selector...

import { createFeatureSelector, createSelector } from "@ngrx/store";
import { AppState } from './app.reducer';

const getAppState = createFeatureSelector<AppState>('app');

export const getUrl = createSelector(
  getAppState,
  state => state.url
  );

In my app.module file...

StoreModule.forRoot(rootReducer),

Within a component...

import * as rootSelectors from '../state/app.selectors';
....

public onUrlBlur(ev : any): void {   
   let val = ev.target.value;
   this.store.dispatch(rootActions.setUrl(val));   
  }

For subscription updates...

this.subs.sink = 
this.store.pipe(select(rootSelectors.getUrl)).subscribe(url => {
this.urlEntered = url        
});

Additionally, in one of my feature modules...

StoreModule.forFeature('myfeature1', {})

Even though I see the blur function being called and results in the redux dev tools, when I check the state, I only see a limited view.

https://i.stack.imgur.com/4twVa.png

I am puzzled as to why my root state does not seem to be properly integrated, and unable to identify what exactly has gone wrong.

Update

I added a similar example that encounters the same issue here

After running the code and checking the console, I noticed the following error message...

The feature name "appRoot" is not found in the state, hence createFeatureSelector cannot access it. Make sure it is imported in a loaded module using StoreModule.forRoot('appRoot', ...) or StoreModule.forFeature('appRoot', ...). If the

I am unsure how to properly utilize

StoreModule.forRoot(rootReducer),

The error recommends using a string like

StoreModule.forRoot('app', rootReducer),
but this leads to syntax errors.

If I try:

StoreModule.forRoot({appRoot: rootReducer}),

This results in a nested state:

https://i.stack.imgur.com/Y0wW6.png

Just passing the reducer without the object wrapper:

StoreModule.forRoot(rootReducer),

Doesn't show any state:

https://i.stack.imgur.com/84VtH.png

Most examples out there focus on feature states, however, I have several settings that are exclusively application-wide, outside of a feature module's scope.

Furthermore, since this state doesn't belong to a feature module, I'm uncertain whether I should use createFeatureSelector:

const getAppState = createFeatureSelector<AppState>('appRoot');

Answer №1

If you are using the StoreModule.forRoot() function, make sure to provide an ActionReducerMap and not just a reducer function.

For more information, refer to the official documentation.

To address the issue with nested states, you can structure it like this:

StoreModule.forRoot({
  tokens: tokensReducer,
  appRoot: appRootReducer
})

Alternatively, you can try:

StoreModule.forRoot({}),
StoreModule.forFeature('appRoot', appRootReducer)

Answer №2

It seems like the reducer may not be set up correctly, causing the action to not update the state. Because the state remains unchanged, the subscription this.store.pipe(select(rootSelectors.getUrl)).subscribe(url => {}) is never triggered.

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

Ways to call a method in a subclass component from a functional parent component?

In my redux-store, I have objects with initial values that are updated in different places within the child component. As the parent, I created a stateless functional component like this: const Parent = () => { const store = useSelector(state => s ...

Update the array state based on the selection of checkboxes and user input in real-time

In my current project using react js, I am working on a UI development task where I need to create a dynamic table based on data fetched from an API. Each row in the table includes a checkbox and a text input field that are dynamically generated. My goal i ...

Tips for preserving dynamically generated HTML through Javascript during page reload

I have a straightforward question, but I haven't been able to find a suitable answer. Here's my situation: On my HTML page, I have a form. Using jQuery and AJAX, I submit the form and then use some JavaScript code to change the content of a spec ...

Incorporating DefinitelyTyped files into an Angular 2 project: A step-by-step guide

I am currently developing an application using angular 2 and node.js. My current task involves installing typings for the project. In the past, when starting the server and activating the TypeScript compiler, I would encounter a log with various errors rel ...

Having Trouble Retrieving Data from Observable in Angular 2 and Typescript

I've encountered a promise error when trying to access a variable that receives data from an observable. Here's an example: Within my component, I have defined the Stat class: export class Stats { name: string; percentage: number; constru ...

Transfer the cropped image to the database through AJAX on the client side and PHP on the server side

I am attempting to upload an image to a Database using JavaScript on the client-side and PHP on the server-side. The first step is selecting an image from the gallery. After zooming and cropping the image, it should be passed to the database. The issue ...

"Can you explain the process by which React grabs the props using the code `const props = this.props

I recently came across an interesting article authored by Dan. The example provided in the article caught my attention: class ProfilePage extends React.Component { showMessage = (user) => { alert('Followed ' + user); }; handleClick ...

Having trouble selecting an element by name that contains a specific string followed by [..] using jQuery

I have elements with names like kra[0][category], kra[1][category], and so on. However, I am facing difficulties in selecting these elements by name. Here is my jQuery code: $("[name=kra[0][category]]").prop("disabled", true); ...

Is there a way to retrieve the row and parent width from a Bootstrap and Aurelia application?

Is there a way to determine the exact width of a bootstrap grid row or grid container in pixels using Aurelia? I attempted to find this information on the bootstrap website, but I am still unsure as there are multiple width dimensions such as col-xs, colm ...

implementing the reuse of form control names for multiple dropdowns in an Angular application

When using the dropdown menu, I am facing an issue where selecting a value from the second dropdown makes it disappear. This is because both dropdowns are using the same formControlName to pass values to the backend with the same header. How can this be fi ...

Having difficulties viewing the sidemenu icon on Ionic 3, despite enabling the menu through MenuController

I am trying to show the sidemenu icon on my Home page, which users can access from the Add-Contract page. Even though I have enabled the sidemenu in home.ts using this.menu.enable(true);, the icon is not visible. However, I can still swipe and access the ...

Is it normal for Node's console to not display all object properties?

After running some code, I noticed something peculiar. console.log(myURL); It seems that the extension property is missing: console.log(myURL.extension); However, when logging it on its own, the value appears correctly. The URL object was created ...

Leverage elements from nearby npm repository when building an Angular 2 application

After developing a generic chart component using d3 and Angular 2, I decided to share it by publishing it in a local npm repository. This way, anyone can easily incorporate the chart component into their Angular project by simply running the npm install my ...

Transforming an Input Field into a String with React's onChange Event

I have a small application consisting of three components Parent Component: App Son Component: Courses Grandchild Component: Course The state of the app is stored in the App component. In the Course component, there is an input field with an onChange ev ...

Toggle Visibility of Elements with Javascript and Html

I've been working on implementing a "Show All / Hide All" feature. Currently, clicking on the text opens the image and text individually. However, I am looking to add a functionality for expanding all divs at once. To see how it currently functions, ...

Utilize VueJS to bind a flat array to a v-model through the selection of multiple checkboxes

My Vue component includes checkboxes that have an array of items as their value: <div v-for="group in groups"> <input type="checkbox" v-model="selected" :value="group"> <template v-for="item in group"> <input type ...

How to Dynamically Update Sass Styles with Webpack 2?

Currently, I am in the process of setting up a React application that utilizes Webpack2, webpack-dev-middleware, and HMR for the development phase. One peculiar issue that I have encountered is related to updating .scss files. When I make changes to my .sc ...

Challenge Encountered while Generating Angular Docker Image using VSTS Pipeline

I'm currently in the process of setting up a VSTS pipeline to create a Docker Image for an Angular Application. I've chosen the "Hosted Windows Container" as the Agent pool, but I'm encountering the following error: Step 1/5: FROM nginx:alp ...

The issue arises when using multiple route files in Route.js, as it hinders the ability to incorporate additional functions within the

After breaking down Route.js into multiple controllers, I'm stuck on why I can't add an extra function to block permissions for viewing the page. // route.js module.exports = function(app, passport) { app.use('/profile&apos ...

What is the best way to differentiate between two calls to the same method that are based on different arguments?

Currently, I am utilizing sinon to mock functions from Google Drive in my NodeJS project. In a single test scenario, I make two separate calls to the create method (without the ability to restore between calls): // Call 1: drive.files.create({ 'reques ...