redux vs mobx vs @ngrx/store vs @datorama/akita vs @ngneat/elf-state-history
State Management Libraries Comparison
1 Year
reduxmobx@ngrx/store@datorama/akita@ngneat/elf-state-historySimilar Packages:
What's State Management Libraries?

State management libraries are essential tools in web development that help manage the state of applications in a predictable and efficient manner. These libraries provide a structured way to handle data flow, making it easier to maintain and debug applications, especially as they grow in complexity. They often implement patterns such as Flux or Observer, allowing developers to manage state changes in a way that promotes consistency and reactivity. Choosing the right state management library can significantly impact the scalability, maintainability, and performance of your application.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
redux12,805,53261,202290 kB43a year agoMIT
mobx1,898,64827,8904.33 MB662 months agoMIT
@ngrx/store777,8098,195636 kB682 months agoMIT
@datorama/akita46,2713,697343 kB482 years agoApache-2.0
@ngneat/elf-state-history7,3231,64537.4 kB92 years agoMIT
Feature Comparison: redux vs mobx vs @ngrx/store vs @datorama/akita vs @ngneat/elf-state-history

Architecture

  • redux:

    Redux is centered around a single store that holds the entire application state. It uses pure functions (reducers) to manage state transitions based on dispatched actions, ensuring that state changes are predictable and traceable.

  • mobx:

    MobX employs a reactive programming model, allowing state to be automatically tracked and updated. This architecture enables developers to create highly responsive applications with minimal boilerplate, focusing on the state and its derivations.

  • @ngrx/store:

    NgRx Store is based on the Redux architecture, promoting a unidirectional data flow. It uses actions, reducers, and selectors to manage state changes, ensuring that the application state is predictable and easy to debug.

  • @datorama/akita:

    Akita follows a simple store pattern that allows developers to manage state in a straightforward manner. It emphasizes a clear separation of concerns and provides a minimalistic API for state management, making it easy to understand and use.

  • @ngneat/elf-state-history:

    Elf State History is built on the principles of the Redux pattern but adds the capability to track state changes over time. This architecture allows developers to easily implement features like undo/redo, making it suitable for applications requiring state history.

Reactivity

  • redux:

    Redux uses a more manual approach to reactivity, where components must explicitly subscribe to state changes. While this can lead to more boilerplate, it provides a clear and predictable flow of data.

  • mobx:

    MobX excels in reactivity, automatically tracking dependencies and updating components when observable state changes. This fine-grained reactivity allows for efficient updates and minimal re-renders, leading to improved performance.

  • @ngrx/store:

    NgRx Store implements a reactive approach through observables, allowing components to subscribe to state slices and react to changes. This ensures that the UI remains in sync with the application state, enhancing the user experience.

  • @datorama/akita:

    Akita provides a reactive store that allows components to subscribe to state changes easily. This reactivity ensures that UI components automatically update when the underlying state changes, promoting a seamless user experience.

  • @ngneat/elf-state-history:

    Elf State History offers built-in reactivity, allowing components to react to state changes and automatically update the UI. This feature is particularly useful for applications that require real-time updates based on user interactions.

Learning Curve

  • redux:

    Redux has a moderate learning curve, as developers must understand the concepts of actions, reducers, and middleware. While it may take some time to master, its widespread use and community support provide ample resources for learning.

  • mobx:

    MobX is known for its simplicity and ease of use, especially for those familiar with reactive programming. Its intuitive API allows developers to quickly implement state management without extensive boilerplate code.

  • @ngrx/store:

    NgRx Store has a steeper learning curve due to its reliance on RxJS and the Redux pattern. Developers need to understand concepts like actions, reducers, and effects, which can be challenging for beginners but rewarding for complex applications.

  • @datorama/akita:

    Akita has a gentle learning curve, making it accessible for developers new to state management. Its straightforward API and clear documentation help developers quickly grasp its concepts and implement it in their applications.

  • @ngneat/elf-state-history:

    Elf State History is relatively easy to learn, especially for those familiar with Redux. Its focus on state history and undo/redo features may require some additional understanding, but overall, it remains approachable.

Middleware and Side Effects

  • redux:

    Redux has a robust middleware system that allows developers to intercept actions and handle side effects. Popular middleware like Redux Thunk and Redux Saga provide powerful tools for managing asynchronous actions and complex workflows.

  • mobx:

    MobX does not have a formal middleware system, but its reactive nature allows for straightforward handling of side effects through reactions and computed values. This can simplify the management of asynchronous operations within the application.

  • @ngrx/store:

    NgRx Store provides a powerful effects library for handling side effects in a structured manner. This allows developers to manage asynchronous actions and side effects cleanly, promoting a clear separation of concerns.

  • @datorama/akita:

    Akita does not have built-in middleware support, but it allows for easy integration with other libraries for handling side effects. Developers can implement their own solutions to manage asynchronous operations as needed.

  • @ngneat/elf-state-history:

    Elf State History supports middleware-like functionality through its state history capabilities, allowing developers to manage side effects related to state changes effectively. This makes it suitable for applications with complex state interactions.

Community and Ecosystem

  • redux:

    Redux boasts a massive community and ecosystem, with numerous libraries, middleware, and tools available. Its widespread adoption means that developers can find extensive resources, tutorials, and community support.

  • mobx:

    MobX has a strong community and is widely used in various applications. Its ecosystem includes a variety of tools and libraries that enhance its capabilities, making it a popular choice for state management in React and other frameworks.

  • @ngrx/store:

    NgRx Store has a large and active community, with extensive documentation, tutorials, and third-party libraries. Its popularity in the Angular ecosystem ensures that developers have access to a wealth of resources and support.

  • @datorama/akita:

    Akita has a growing community and ecosystem, with a focus on Angular applications. While it may not be as widely adopted as some other libraries, it is gaining traction and has good documentation and support.

  • @ngneat/elf-state-history:

    Elf State History is relatively new but is part of the growing ecosystem around state management in Angular. Its community is expanding, and it benefits from modern design principles that appeal to developers.

How to Choose: redux vs mobx vs @ngrx/store vs @datorama/akita vs @ngneat/elf-state-history
  • redux:

    Select Redux if you are looking for a widely adopted state management solution that follows the Flux architecture and provides a predictable state container. It is ideal for applications that require a centralized store and want to leverage middleware for handling asynchronous actions.

  • mobx:

    Choose MobX if you prefer a more reactive programming model that allows for automatic dependency tracking and state updates. It is particularly beneficial for applications that require fine-grained reactivity and want to minimize boilerplate code, making it easier to manage complex state interactions.

  • @ngrx/store:

    Opt for NgRx Store if you are building a large-scale Angular application that requires a robust state management solution based on the Redux pattern. It is suitable for applications that benefit from a strict unidirectional data flow and require advanced features like effects and selectors for handling side effects and derived state.

  • @datorama/akita:

    Choose Akita if you need a simple yet powerful state management solution that is easy to integrate and provides a clear structure for managing state in Angular applications. It is particularly useful for projects that require a store with minimal boilerplate and a focus on simplicity.

  • @ngneat/elf-state-history:

    Select Elf State History if you want a state management solution that emphasizes history tracking and undo/redo capabilities. This package is ideal for applications where tracking changes and state history is crucial, such as in forms or complex workflows.

README for redux

Redux Logo

Redux is a predictable state container for JavaScript apps.

It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as live code editing combined with a time traveling debugger.

You can use Redux together with React, or with any other view library. The Redux core is tiny (2kB, including dependencies), and has a rich ecosystem of addons.

Redux Toolkit is our official recommended approach for writing Redux logic. It wraps around the Redux core, and contains packages and functions that we think are essential for building a Redux app. Redux Toolkit builds in our suggested best practices, simplifies most Redux tasks, prevents common mistakes, and makes it easier to write Redux applications.

GitHub Workflow Status npm version npm downloads redux channel on discord

Installation

Create a React Redux App

The recommended way to start new apps with React and Redux Toolkit is by using our official Redux Toolkit + TS template for Vite, or by creating a new Next.js project using Next's with-redux template.

Both of these already have Redux Toolkit and React-Redux configured appropriately for that build tool, and come with a small example app that demonstrates how to use several of Redux Toolkit's features.

# Vite with our Redux+TS template
# (using the `degit` tool to clone and extract the template)
npx degit reduxjs/redux-templates/packages/vite-template-redux my-app

# Next.js using the `with-redux` template
npx create-next-app --example with-redux my-app

We do not currently have official React Native templates, but recommend these templates for standard React Native and for Expo:

  • https://github.com/rahsheen/react-native-template-redux-typescript
  • https://github.com/rahsheen/expo-template-redux-typescript
npm install @reduxjs/toolkit react-redux

For the Redux core library by itself:

npm install redux

For more details, see the Installation docs page.

Documentation

The Redux core docs are located at https://redux.js.org, and include the full Redux tutorials, as well usage guides on general Redux patterns:

The Redux Toolkit docs are available at https://redux-toolkit.js.org, including API references and usage guides for all of the APIs included in Redux Toolkit.

Learn Redux

Redux Essentials Tutorial

The Redux Essentials tutorial is a "top-down" tutorial that teaches "how to use Redux the right way", using our latest recommended APIs and best practices. We recommend starting there.

Redux Fundamentals Tutorial

The Redux Fundamentals tutorial is a "bottom-up" tutorial that teaches "how Redux works" from first principles and without any abstractions, and why standard Redux usage patterns exist.

Help and Discussion

The #redux channel of the Reactiflux Discord community is our official resource for all questions related to learning and using Redux. Reactiflux is a great place to hang out, ask questions, and learn - please come and join us there!

Before Proceeding Further

Redux is a valuable tool for organizing your state, but you should also consider whether it's appropriate for your situation. Please don't use Redux just because someone said you should - instead, please take some time to understand the potential benefits and tradeoffs of using it.

Here are some suggestions on when it makes sense to use Redux:

  • You have reasonable amounts of data changing over time
  • You need a single source of truth for your state
  • You find that keeping all your state in a top-level component is no longer sufficient

Yes, these guidelines are subjective and vague, but this is for a good reason. The point at which you should integrate Redux into your application is different for every user and different for every application.

For more thoughts on how Redux is meant to be used, please see:

Basic Example

The whole global state of your app is stored in an object tree inside a single store. The only way to change the state tree is to create an action, an object describing what happened, and dispatch it to the store. To specify how state gets updated in response to an action, you write pure reducer functions that calculate a new state based on the old state and the action.

Redux Toolkit simplifies the process of writing Redux logic and setting up the store. With Redux Toolkit, the basic app logic looks like:

import { createSlice, configureStore } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    incremented: state => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1
    },
    decremented: state => {
      state.value -= 1
    }
  }
})

export const { incremented, decremented } = counterSlice.actions

const store = configureStore({
  reducer: counterSlice.reducer
})

// Can still subscribe to the store
store.subscribe(() => console.log(store.getState()))

// Still pass action objects to `dispatch`, but they're created for us
store.dispatch(incremented())
// {value: 1}
store.dispatch(incremented())
// {value: 2}
store.dispatch(decremented())
// {value: 1}

Redux Toolkit allows us to write shorter logic that's easier to read, while still following the original core Redux behavior and data flow.

Logo

You can find the official logo on GitHub.

Change Log

This project adheres to Semantic Versioning. Every release, along with the migration instructions, is documented on the GitHub Releases page.

License

MIT