Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for When and Why to Use REDUX NgRx in Angular
Dany Paredes
Dany Paredes

Posted on • Originally published atdanywalls.com

     

When and Why to Use REDUX NgRx in Angular

In a previous article, I wrote about managing thestate in Angular by using Services, but when the application increases in size and needs to track and handle a large state, it becomes a bit complex and not easy to manage. For example, when we have many components that need to react to those changes in the state.

At the beginning, using a service with a behavior subject is easy, but sometimes we start to encounter issues or side effects that make it hard to identify where the problem is occurring.

In our apps, we may handle a few types of state: sometimes persistent in the backend and coming from an API, in the URL state likehttp://myapp.com/users?id=2, or in a single component. So, when I really needs to use NgRx? 🤔

Do You Need Use NgRx ?

Well, NgRx is a great tool, but I don't use it for all my applications. Why? Before starting with NgRx, I ask myself some questions:

  • Is my app small and an MVP?

  • Do I need a state, and my components don't need to react to other state changes?

  • Do my teammates also know RxJS and Redux?

If you answer yes, then you don't need NgRx. Because NgRx requires a good knowledge of RxJS and involves writing boilerplate code. So, if you are working on something small or delivering your MVP, try building usingAngular Services with Behavior or consider@ngrx/component-store as a good alternative.

But, if this is not your scenario and you want to continue with NgRx, then ask the next questions about your state.

  • Is it fetched by many components and services?

  • Is it persisted and change by others sources?

  • Is it changed by action from other sources?

  • Is it Needs to be ready for routes?

  • Is It Fetched by a side-effect ?

If most of that questions are true, then you need to use NgRx . Maybe the best way to figure out if really needs is with the following example. The Nba.com it have many interactions by the users also, needs to keep the state in the router, components, react change in the feed an more other points like:

  • The URL is linked with the state of the calendar and filters.

  • The calendars filter the data and the user can change it, but also update the URL.

  • the game feed of games must to react to changes in realtime.

1

In case the user have many interactions and the components must to react to them with multiple datasources. NgRx provides a set of libraries like@ngrx/store,@ngrx/effects,@ngrx/router-store,@ngrx/entity,@ngrx/component-store,@ngrx/signals and@ngrx/operators to help us build reactive and global state with isolation of side effects , also works entities collection integration with the Angular router and with a easy way to debug using adevtools.

NgRx makes it easy to organize and manage the state because it follows the REDUX pattern, so we have:

  • A Single source of truthstore.

  • The State is read-only , only way to change is dispatching actions.

  • The reducers are pure functions responsible to change the State.

  • Provide Selectors to get specific slice of the state.

All those parts have a workflow to follow, and each one has its own responsibility during the process. So now, let's discuss the NgRx workflow.

NgRx Workflow

For example, in my Angular app, thehome.component requires the user to accept the terms and conditions. After accepting, the user navigates to the about page. However, when they return to the home page, the terms and conditions checkbox is unchecked again 🙃.

Why doesn't my app keep the state?

Well, thehome.component was destroyed and the state disappear, when the user move to about, and the home.component don't store the state in any place, I think it a perfect small case to solve with NgRx and to show how NgRx workflow works.

Yes, it is a easy case to solve with a Behavior Subject, but its the most easy way to show the NgRx workflow.

The NgRx workflow is based onActions,Reducer,Store andSelectors (andEffect when needs), so the workflow must to be:

  • The component trigger an action[TermsCondition Page] Accept Terms Conditions

  • Thereducer get theaction trigger ,function getting a copy of the currentstate make the changes and update the state.

  • The component can read the change in the state by using aselectors or from the globalstore.

2

Setup Project

Instead of building an app from scratch, I prefer to provide you with a repo as the starting point. In my case, I'm using Angular with Standalone (no modules).

First, in the terminal, run the following code to clone the repo and install the dependencies.

git clone https://github.com/danywalls/start-with-ngrx.gitnpm i
Enter fullscreen modeExit fullscreen mode

Next, runng serve to start the example application and navigate tohttp://localhost:4200. On the home page, check the checkbox. Then, click on "About" and go back to "Home." You will see that the checkbox is no longer checked.

3

We have the scenario ready, so it's time to fix it using NgRx! ⚒️

Configure NgRx

Next install ngrx by running the commandnpm i @ngrx/store :

npm i @ngrx/store
Enter fullscreen modeExit fullscreen mode

Open theapp.config.ts file. In the providers section, use theprovideStore function to configure the global state. It expects the state and reducer, but since we don't have the reducer ready, initialize it with an empty function for now.

import{provideRouter}from'@angular/router';import{routes}from'./app.routes';import{provideStore}from'@ngrx/store';exportconstappConfig={providers:[provideRouter(routes),provideStore()],};
Enter fullscreen modeExit fullscreen mode

Next, we need to set up the state for the home page. Create a new directory:pages/home/home.state.ts. Inside, create an interface for theHomeState and define theinitialState.

the state is a object with the properties to expose by the state.

exportinterfaceHomeState{acceptTerms:boolean}constinitialState:HomeState={acceptTerms:false,}
Enter fullscreen modeExit fullscreen mode

We have the state ready, so let's create the reducer inpages/home/state/home.reducer.ts. Import thecreateReducer function with theinitialState and import theon function.

Import thecreateAction function to define the action. Pass the action name[Home Page] Accept Terms and, as a parameter, the state.

Use the spread operator (...) to get the current value ofstate and update theacceptTerms property.

The final code looks like:

import{createAction,createReducer,on}from'@ngrx/store';import{initialState}from'./home.state';exportconsthomeReducer=createReducer(initialState,on(createAction('[Home Page] Accept Terms'),(state)=>({...state,acceptTerms:!state.acceptTerms,})),);
Enter fullscreen modeExit fullscreen mode

We are now ready to initialize the store. Open theapp.config.ts file again and add the home slice object to the reducer using thehomeReducer.

Another option is useprovideState

import{provideRouter}from'@angular/router';import{routes}from'./app.routes';import{provideStore,StoreModule}from"@ngrx/store";import{homeReducer}from"./pages/home/state/home.reducer";exportconstappConfig={providers:[provideRouter(routes),provideStore({home:homeReducer,})]};
Enter fullscreen modeExit fullscreen mode

Using NgRx

We are in the final steps. First, open thehome.component.ts file and inject thestore. Next, store$acceptTerms from the store. For this article, I want to skip theselector, so I will subscribe directly to thestore usingselect and transform the observable to a signal using thetoSignal function to avoid subscribing with theasync pipe.

We make a small change in theonChange method. Using the store, we dispatch the action to trigger the update from the reducer.

The final code looks like this:

exportclassHomeComponent{private_store=inject(Store);public$acceptTerms=toSignal(this._store.select((state)=>state.home.acceptTerms))onChange(){this._store.dispatch({type:'[Home Page] Accept Terms'})}}
Enter fullscreen modeExit fullscreen mode

In the template, update the logic to use the$acceptTerms signal by reading the value with().

@if(!$acceptTerms()) {<h3>Do you want to use NgRx?</h3><input(change)="onChange()"[value]="$acceptTerms()"type="checkbox">} @else {<h2>Thanks for love NgRx🎉🥳</h2>}
Enter fullscreen modeExit fullscreen mode

Save the changes and ta-da! 🎉🎉🎉 NgRx is now set up, and the state is integrated into our app!

4

Conclusion

We learned how easy it is to create a state, action, and reducer, and read the state directly using the store. However, for a small application, it might feel like too much boilerplate, but it's a great starting point with NgRx.

We also have examples of when to use NgRx over Angular Services. You can use the checklist to decide if NgRx is necessary.

Finally, I learned with a basic practical example how to configure NgRx to manage state. This includes setting up the store, creating state and reducers, and integrating NgRx into a component to easily maintain state across navigation.

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
jangelodev profile image
João Angelo
Full Stack Developer | Angular, Nx and .NET Core Expert | Building high-performance, scalable and secure solutions for the web.
  • Location
    Brazil
  • Pronouns
    He / Him
  • Joined

Hi Dany Paredes,
Top, very nice and helpful !
Thanks for sharing.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I'm an NBA lover, GDE in Angular, love work with Angular, Typescript and Testing Library, and sharing content in danywalls.com and ng-content.com
  • Location
    Barcelona
  • Joined

More fromDany Paredes

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp