Convert Figma logo to code with AI

ngrx logostore

RxJS powered state management for Angular applications, inspired by Redux

3,899
311
3,899
10

Top Related Projects

96,481

Deliver web apps with confidence 🚀

28,431

🗃️ Centralized State Management for Vue.js.

60,936

A JS library for predictable global state management

27,618

Simple, scalable state management.

230,431

The library for web and native user interfaces.

30,950

A reactive programming library for JavaScript

Quick Overview

NgRx Store is a state management library for Angular applications, inspired by Redux. It provides a robust architecture for managing application state, enabling predictable state mutations through actions and reducers, and offering powerful tools for handling side effects and optimizing performance.

Pros

  • Centralized state management for complex Angular applications
  • Immutable state updates, leading to more predictable behavior
  • Powerful dev tools for debugging and time-travel debugging
  • Excellent integration with Angular's change detection mechanism

Cons

  • Steep learning curve for developers new to Redux-style state management
  • Can be overkill for small to medium-sized applications
  • Requires writing more boilerplate code compared to simpler state management solutions
  • Performance overhead for very large state trees

Code Examples

  1. Defining an action:
import { createAction, props } from '@ngrx/store';

export const addTodo = createAction(
  '[Todo] Add Todo',
  props<{ text: string }>()
);
  1. Creating a reducer:
import { createReducer, on } from '@ngrx/store';
import { addTodo } from './todo.actions';

export interface TodoState {
  todos: string[];
}

export const initialState: TodoState = {
  todos: []
};

export const todoReducer = createReducer(
  initialState,
  on(addTodo, (state, { text }) => ({
    ...state,
    todos: [...state.todos, text]
  }))
);
  1. Selecting state in a component:
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-todo-list',
  template: `
    <ul>
      <li *ngFor="let todo of todos$ | async">{{ todo }}</li>
    </ul>
  `
})
export class TodoListComponent {
  todos$: Observable<string[]>;

  constructor(private store: Store<{ todos: string[] }>) {
    this.todos$ = store.select(state => state.todos);
  }
}

Getting Started

  1. Install NgRx Store:
ng add @ngrx/store
  1. Define your state interface and initial state in a file (e.g., app.state.ts):
export interface AppState {
  // Define your state properties here
}

export const initialState: AppState = {
  // Initialize your state here
};
  1. Create actions and reducers for your state.

  2. Register your reducers in your app.module.ts:

import { StoreModule } from '@ngrx/store';
import { reducers } from './reducers';

@NgModule({
  imports: [
    StoreModule.forRoot(reducers)
  ]
})
export class AppModule { }
  1. Inject the Store into your components and start using it to select state and dispatch actions.

Competitor Comparisons

96,481

Deliver web apps with confidence 🚀

Pros of Angular

  • Comprehensive framework with built-in features for routing, forms, and HTTP communication
  • Extensive ecosystem with official libraries and third-party components
  • Powerful CLI for project scaffolding, development, and build optimization

Cons of Angular

  • Steeper learning curve due to its comprehensive nature
  • Larger bundle size compared to more lightweight solutions
  • Opinionated structure may feel restrictive for some developers

Code Comparison

Angular (component):

@Component({
  selector: 'app-root',
  template: '<h1>{{ title }}</h1>'
})
export class AppComponent {
  title = 'My Angular App';
}

NgRx Store (reducer):

export const counterReducer = createReducer(
  initialState,
  on(increment, state => state + 1),
  on(decrement, state => state - 1)
);

Key Differences

  • Angular is a full-featured framework, while NgRx Store is a state management library
  • Angular provides a complete solution for building applications, whereas NgRx Store focuses on managing application state
  • NgRx Store is often used within Angular applications to handle complex state management scenarios

Use Cases

  • Angular: Building large-scale, feature-rich web applications
  • NgRx Store: Managing complex application state in Angular projects, especially those with intricate data flows and frequent state updates

Community and Support

  • Angular: Larger community, extensive documentation, and official support from Google
  • NgRx Store: Smaller but active community, well-maintained documentation, and regular updates
28,431

🗃️ Centralized State Management for Vue.js.

Pros of Vuex

  • Simpler learning curve and easier to set up
  • Tighter integration with Vue.js ecosystem
  • More concise syntax for common operations

Cons of Vuex

  • Less scalable for large applications
  • Fewer built-in features for handling side effects
  • Limited TypeScript support compared to NgRx

Code Comparison

Vuex:

const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    increment(state) { state.count++ }
  }
})

NgRx:

export const counterReducer = createReducer(
  initialState,
  on(increment, (state) => ({ ...state, count: state.count + 1 }))
);

Both Store and Vuex are state management libraries for their respective frameworks (Angular and Vue.js). Store offers a more robust, Redux-inspired approach with better TypeScript integration and scalability for large applications. Vuex, on the other hand, provides a simpler, more Vue-centric solution that's easier to learn and integrate into smaller projects.

Store emphasizes immutability and uses pure functions (reducers) to handle state changes, while Vuex allows direct state mutations within its mutation handlers. This difference reflects the underlying philosophy of each library, with Store focusing on predictability and Vuex prioritizing simplicity.

60,936

A JS library for predictable global state management

Pros of Redux

  • Framework-agnostic, can be used with any JavaScript library or framework
  • Larger ecosystem with more middleware and extensions available
  • Simpler learning curve for developers new to state management

Cons of Redux

  • More boilerplate code required for setup and actions
  • Less type safety compared to NgRx's TypeScript integration
  • Manual implementation of features like entity management and effects

Code Comparison

Redux:

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    default:
      return state
  }
}

NgRx:

export const counterReducer = createReducer(
  0,
  on(increment, (state) => state + 1)
);

NgRx leverages TypeScript for better type inference and uses a more declarative approach with its createReducer and on functions. Redux, on the other hand, typically uses switch statements in its reducers, which can be more verbose but are also more familiar to developers coming from other languages or frameworks.

Both libraries follow similar principles of immutable state updates and unidirectional data flow, but NgRx is more tightly integrated with Angular and provides additional features out of the box, such as effects for handling side effects and entity management for simplified CRUD operations.

27,618

Simple, scalable state management.

Pros of MobX

  • Simpler learning curve and less boilerplate code
  • More flexible and less opinionated about state management structure
  • Automatic tracking of observables, reducing manual updates

Cons of MobX

  • Less predictable state changes due to mutable state
  • Potential for overuse of observables, leading to performance issues
  • Lack of built-in middleware support for handling side effects

Code Comparison

MobX:

import { makeObservable, observable, action } from "mobx";

class Store {
  count = 0;
  constructor() {
    makeObservable(this, {
      count: observable,
      increment: action
    });
  }
  increment() {
    this.count++;
  }
}

NgRx Store:

import { createAction, createReducer, on } from '@ngrx/store';

export const increment = createAction('[Counter] Increment');

export const counterReducer = createReducer(
  0,
  on(increment, (state) => state + 1)
);

MobX offers a more straightforward approach with less code, while NgRx Store provides a more structured and predictable state management solution. MobX's simplicity comes at the cost of potential complexity in larger applications, whereas NgRx Store's verbosity offers better scalability and maintainability for complex state management scenarios.

230,431

The library for web and native user interfaces.

Pros of React

  • More comprehensive UI library, offering a complete solution for building user interfaces
  • Larger ecosystem and community support, with numerous third-party libraries and tools
  • Easier learning curve for beginners due to its component-based architecture

Cons of React

  • Heavier and more complex than NgRx/Store, which focuses solely on state management
  • May require additional libraries for state management in large applications
  • More opinionated about application structure, potentially limiting flexibility

Code Comparison

React component example:

function Counter({ count, onIncrement }) {
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={onIncrement}>Increment</button>
    </div>
  );
}

NgRx/Store action and reducer example:

const increment = createAction('[Counter] Increment');

const counterReducer = createReducer(0,
  on(increment, state => state + 1)
);

While React focuses on UI components, NgRx/Store specializes in state management. React's code is more declarative and UI-centric, while NgRx/Store emphasizes actions and reducers for managing application state.

30,950

A reactive programming library for JavaScript

Pros of RxJS

  • More versatile and can be used in various JavaScript environments, not limited to Angular
  • Provides a rich set of operators for complex data transformations and combinations
  • Suitable for handling asynchronous operations beyond just state management

Cons of RxJS

  • Steeper learning curve due to its extensive API and reactive programming concepts
  • Can lead to overly complex code if not used judiciously
  • Lacks built-in state management features, requiring additional setup for that purpose

Code Comparison

RxJS:

import { of } from 'rxjs';
import { map } from 'rxjs/operators';

const source$ = of(1, 2, 3);
const result$ = source$.pipe(map(x => x * 2));
result$.subscribe(console.log);

NgRx Store:

import { createAction, createReducer, on } from '@ngrx/store';

const increment = createAction('[Counter] Increment');
const decrement = createAction('[Counter] Decrement');

const counterReducer = createReducer(0,
  on(increment, state => state + 1),
  on(decrement, state => state - 1)
);

Summary

RxJS is a powerful library for reactive programming, offering flexibility and a wide range of operators for handling asynchronous data streams. It can be used across different JavaScript frameworks and environments. However, it has a steeper learning curve and doesn't provide built-in state management features like NgRx Store does. NgRx Store, built on top of RxJS, offers a more structured approach to state management specifically tailored for Angular applications, with a focus on predictable state mutations and easier debugging.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README


This repository is for version 2.x of @ngrx/store.

Click here for the latest version (4.x)


@ngrx/store

RxJS powered state management for Angular applications, inspired by Redux

Join the chat at https://gitter.im/ngrx/store CircleCI Status for ngrx/store npm version

@ngrx/store is a controlled state container designed to help write performant, consistent applications on top of Angular. Core tenets:

  • State is a single immutable data structure
  • Actions describe state changes
  • Pure functions called reducers take the previous state and the next action to compute the new state
  • State accessed with the Store, an observable of state and an observer of actions

These core principles enable building components that can use the OnPush change detection strategy giving you intelligent, performant change detection throughout your application.

Installation

Install @ngrx/core and @ngrx/store from npm:

npm install @ngrx/core @ngrx/store@2.2.3 --save

Optional packages:

Examples

  • Official @ngrx/example-app is an officially maintained example application showcasing best practices for @ngrx projects, including @ngrx/store and @ngrx/effects
  • angular-webpack2-starter is a complete Webpack 2 starter with built-in support for @ngrx. Includes Ahead-of-Time (AOT) compilation, hot module reloading (HMR), devtools, and server-side rendering.

Introduction

Setup

Create a reducer function for each data type you have in your application. The combination of these reducers will make up your application state:

// counter.ts
import { ActionReducer, Action } from '@ngrx/store';

export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const RESET = 'RESET';

export function counterReducer(state: number = 0, action: Action) {
	switch (action.type) {
		case INCREMENT:
			return state + 1;

		case DECREMENT:
			return state - 1;

		case RESET:
			return 0;

		default:
			return state;
	}
}

In your app's main module, import those reducers and use the StoreModule.provideStore(reducers) function to provide them to Angular's injector:

import { NgModule } from '@angular/core'
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter';

@NgModule({
  imports: [
    BrowserModule,
    StoreModule.provideStore({ counter: counterReducer })
  ]
})
export class AppModule {}

You can then inject the Store service into your components and services. Use store.select to select slice(s) of state:

import { Store } from '@ngrx/store';
import { INCREMENT, DECREMENT, RESET } from './counter';

interface AppState {
  counter: number;
}

@Component({
	selector: 'my-app',
	template: `
		<button (click)="increment()">Increment</button>
		<div>Current Count: {{ counter | async }}</div>
		<button (click)="decrement()">Decrement</button>

		<button (click)="reset()">Reset Counter</button>
	`
})
class MyAppComponent {
	counter: Observable<number>;

	constructor(private store: Store<AppState>){
		this.counter = store.select('counter');
	}

	increment(){
		this.store.dispatch({ type: INCREMENT });
	}

	decrement(){
		this.store.dispatch({ type: DECREMENT });
	}

	reset(){
		this.store.dispatch({ type: RESET });
	}
}

Contributing

Please read contributing guidelines here.

NPM DownloadsLast 30 Days