Skip to content

Getting started with ngrx/store

Posted on:January 10, 2023 at 12:00 AM

Table of contents

Open Table of contents

Introduction

NGRX Store is a library for managing state in Angular applications. It is built on top of RxJS, which is a library for reactive programming using Observables. NGRX Store provides a way to organize your application’s state into a single, immutable data store, and allows you to manage and update the state using a set of powerful tools and concepts.

NGRX Store uses a centralized store to hold the state of your application, which makes it easy to share the state between different components and services. The state is represented as an Observable, which makes it easy to subscribe to changes and react to them.

NGRX Store also provides a set of powerful tools for managing the state, such as Actions, Reducers, and Effects. Actions are used to represent events that occur in the application, such as a user clicking a button. Reducers are used to update the state based on the actions that occur. And Effects are used to handle side effects, such as making an HTTP request.

By using NGRX Store, you can write more predictable, testable, and maintainable code. It also gives you a consistent way to handle state management across your application, which makes it easier to reason about the behavior of your application.

NGRX also have other packages such as NGRX Effects, NGRX Entity, NGRX Router-Store, etc. which work as extensions to the base NGRX/store and provide more specific functionality.

Benefits of using ngrx/store

There are several benefits to using NGRX Store in your Angular applications:

Installation

Installing NGRX Store in an Angular application is a two-step process:

npm install @ngrx/store @ngrx/effects @ngrx/entity
yarn add @ngrx/store @ngrx/effects @ngrx/entity
import { StoreModule } from '@ngrx/store';
import { reducer } from './reducers';

@NgModule({
  imports: [
    StoreModule.forRoot({ state: reducer })
  ]
})
export class AppModule {}

Note that in the above example I’m importing reducer function from a reducers.ts file. This is where you will define all the logic of your state management using Actions, Reducers, Effects.

You also need to import the store in your component where you want to use it.

import { Store } from '@ngrx/store';

constructor(private store: Store) {}

It is also a good practice to organize the state and actions in a specific way, like creating a folder for each feature and a file for each action, reducer and effect.

You may also consider adding the ngrx dev tools to your browser to have a better developer experience

npm install @ngrx/store-devtools
import { StoreDevtoolsModule } from '@ngrx/store-devtools';

and then import it on your app.module.ts

imports: [
    StoreModule.forRoot({ state: reducer }),
    StoreDevtoolsModule.instrument()
  ]

It is also good to read the official documentation and the guidelines to have a deeper understanding of how to structure your state management and have a better organization and performance.

Example

Here is a simple example of how you might use NGRX Store in an Angular application. Let’s say we have a simple application that allows the user to increment or decrement a counter. Here’s how we might set up the store to manage the state of the counter:

export interface CounterState {
  count: number;
}

export const initialState: CounterState = {
  count: 0
};
import { createAction, props } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
import { createReducer, on } from '@ngrx/store';
import { increment, decrement } from './counter.actions';
import { CounterState, initialState } from './counter.state';

export const counterReducer = createReducer(initialState,
  on(increment, state => ({ count: state.count + 1 })),
  on(decrement, state => ({ count: state.count - 1 })),
);
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter.reducer';

@NgModule({
  imports: [
    StoreModule.forRoot({ count: counterReducer })
  ]
})
export class AppModule {}
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { increment, decrement } from './counter.actions';

@Component({
  selector: 'app-root',
  template: `
    <button (click)="decrement()">-</button>
    <span>{{ count }}</span>
    <button (click)="increment()">+</button>
  `
})
export class AppComponent {
  count: number;

  constructor(private store: Store) {
    store.select('count').subscribe(count => this.count = count);
  }

  increment() {
    this.store.dispatch(increment());
  }

  decrement() {
    this.store.dispatch(decrement());
  }
}

Scenarios where ngrx/store can be useful

NGRX Store is particularly useful in Angular applications that have a complex state or that need to handle a large amount of data. Here are a few scenarios in which NGRX Store can be useful:

Overall, NGRX store is useful in applications that need a powerful and predictable way to manage state, and that benefit from its separation of concerns, immutability and powerful tools.

Downsides

NGRX Store is a powerful tool for managing state in Angular applications, but it also has some downsides:

It’s important to consider these downsides when deciding whether to use NGRX Store in your application, and to weigh the benefits against the potential costs. In many cases, NGRX Store can be a powerful tool for managing state in Angular applications, but it may not be the best choice for every situation.

How can I learn more?

There are many resources available to help you learn more about NGRX Store, here are a few places to start:

In addition to these resources, it’s also important to keep in mind that learning is an ongoing process, you will learn more as you work with NGRX store and encounter new challenges and edge cases.

Alternatives

There are several other libraries and tools available for managing state in Angular applications, here are a few alternatives to NGRX Store:

Ultimately, the best choice will depend on the needs of your specific application and the preferences of your development team. It’s important to evaluate the features, performance and complexity of each library, as well as their adaptability to your use case, before making a final decision.

Conclusion

NGRX Store is a powerful tool for managing state in Angular applications, and it’s a well-established and widely used library. It provides a centralized state management approach, using immutability and a set of powerful tools such as Actions, Reducers and Effects. These tools provide many benefits such as predictability, testability, scalability, and making the application more maintainable.

However, like any tool, NGRX Store isn’t a silver bullet, and it may not be the best choice for every situation. There is a learning curve and some added complexity associated with using NGRX Store, and it may not be necessary for applications with simple state. It’s important to weigh the benefits and downsides of NGRX Store before deciding to use it in your application, and to consider the requirements of your specific use case.

In conclusion, NGRX Store is a powerful library for managing state in Angular applications, and it’s a great tool for large or complex state, real-time applications, undo/redo functionality and multi-module applications. But it’s important to understand its complexity, performance and requirements before deciding to use it, and to consider the alternatives that might suit better the application needs.