jotai vs mobx vs react-query vs recoil vs redux vs valtio vs xstate vs zustand
State Management Libraries for React
jotaimobxreact-queryrecoilreduxvaltioxstatezustandSimilar Packages:

State Management Libraries for React

State management libraries are essential tools in React development, enabling developers to manage application state in a predictable and efficient manner. These libraries provide various methodologies for handling state, allowing for better organization, scalability, and maintainability of applications. They help in managing local and global state, asynchronous data fetching, and side effects, which are crucial for building complex user interfaces. Each library has its unique approach, catering to different needs and preferences, making it essential to understand their features and use cases for optimal selection.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
jotai3,360,78221,103526 kB1613 days agoMIT
mobx3,044,92728,1824.35 MB806 months agoMIT
react-query1,528,36349,0232.26 MB1593 years agoMIT
recoil019,5072.21 MB3223 years agoMIT
redux061,442290 kB412 years agoMIT
valtio010,153101 kB4a month agoMIT
xstate029,3942.26 MB1348 days agoMIT
zustand057,64395 kB421 days agoMIT

Feature Comparison: jotai vs mobx vs react-query vs recoil vs redux vs valtio vs xstate vs zustand

State Management Approach

  • jotai:

    Jotai uses an atomic state management model, where each piece of state is an atom. This allows for granular updates and reactivity, ensuring that only the components that depend on a specific atom re-render when that atom's state changes.

  • mobx:

    MobX employs an observable-based state management approach, allowing for automatic tracking of state changes and reactivity. It simplifies state management by allowing you to define observable state and reactions that automatically update when the state changes.

  • react-query:

    React Query focuses on server state management, providing tools for fetching, caching, and synchronizing server data with the client. It abstracts the complexities of data fetching and caching, making it easier to manage asynchronous data in React applications.

  • recoil:

    Recoil introduces a state management model that combines the benefits of both atomic and derived state. It allows for fine-grained control over state and enables derived state calculations, making it suitable for complex applications with interdependent state.

  • redux:

    Redux uses a centralized store and a unidirectional data flow to manage application state. It emphasizes immutability and pure functions, making state changes predictable and easier to debug, but can introduce boilerplate code.

  • valtio:

    Valtio offers a proxy-based state management approach, allowing for mutable state while keeping reactivity intact. It simplifies state management by enabling direct manipulation of state objects without the need for reducers or actions.

  • xstate:

    XState is a state management library based on finite state machines and statecharts. It provides a robust way to manage complex state transitions and side effects, making it ideal for applications with intricate workflows and states.

  • zustand:

    Zustand is a minimalistic state management library that uses hooks for managing state. It allows for a simple API and encourages the use of React's built-in features, making it lightweight and easy to integrate.

Learning Curve

  • jotai:

    Jotai has a low learning curve, especially for developers familiar with React hooks. Its API is straightforward and easy to grasp, making it accessible for newcomers to state management.

  • mobx:

    MobX is relatively easy to learn, particularly for those with a background in object-oriented programming. Its observable pattern is intuitive, but understanding the reactivity model may take some time for beginners.

  • react-query:

    React Query has a moderate learning curve, as it introduces concepts like caching and server state management. However, its documentation is comprehensive, aiding in the learning process.

  • recoil:

    Recoil's learning curve is gentle for those familiar with React, as it integrates seamlessly with React's mental model. However, understanding its advanced features may require additional time.

  • redux:

    Redux has a steeper learning curve due to its concepts of actions, reducers, and middleware. It requires a good understanding of functional programming principles, which may be challenging for some developers.

  • valtio:

    Valtio is easy to learn, especially for those familiar with JavaScript proxies. Its API is simple and intuitive, allowing developers to quickly grasp its usage.

  • xstate:

    XState has a higher learning curve, as it introduces state machines and statecharts, which may be unfamiliar to many developers. However, it provides a powerful model for managing complex states.

  • zustand:

    Zustand is straightforward and easy to learn, with a minimal API that is intuitive for React developers. Its simplicity allows for quick onboarding.

Performance

  • jotai:

    Jotai is optimized for performance, as it only re-renders components that depend on changed atoms. This fine-grained reactivity minimizes unnecessary renders and enhances application performance.

  • mobx:

    MobX is highly performant due to its automatic dependency tracking and fine-grained reactivity. It minimizes re-renders by only updating components that directly depend on the changed observable state.

  • react-query:

    React Query excels in performance by caching server data and minimizing network requests. It intelligently refetches data only when necessary, improving the overall responsiveness of applications.

  • recoil:

    Recoil offers good performance through its atomic state model, ensuring that only components subscribed to changed atoms re-render. This selective rendering helps maintain application efficiency.

  • redux:

    Redux can introduce performance bottlenecks if not managed correctly, particularly with large state trees. However, using techniques like memoization and selectors can mitigate these issues.

  • valtio:

    Valtio provides excellent performance by allowing mutable state while maintaining reactivity. Its proxy-based approach ensures efficient updates and minimal re-renders.

  • xstate:

    XState can be performant for complex state management, but the overhead of managing state machines may introduce some latency. Properly designed statecharts can optimize performance for intricate workflows.

  • zustand:

    Zustand is lightweight and performant, as it allows for direct state manipulation without unnecessary re-renders. Its simplicity contributes to efficient state management.

Extensibility

  • jotai:

    Jotai is highly extensible, allowing developers to create custom atoms and hooks, making it adaptable to various application needs and architectures.

  • mobx:

    MobX is extensible through decorators and custom observable structures, enabling developers to tailor the state management to their specific requirements.

  • react-query:

    React Query is extensible with custom hooks and query functions, allowing developers to integrate it seamlessly with other libraries and APIs, enhancing its capabilities.

  • recoil:

    Recoil supports extensibility through its atom and selector model, enabling developers to create complex state relationships and derived state calculations easily.

  • redux:

    Redux is highly extensible, with a rich ecosystem of middleware and libraries that enhance its functionality. Developers can create custom reducers and actions to fit their application needs.

  • valtio:

    Valtio is extensible by allowing developers to create custom proxies and state structures, making it flexible for various use cases and architectures.

  • xstate:

    XState is extensible through the use of custom state machines and transitions, allowing developers to define complex workflows and behaviors tailored to their applications.

  • zustand:

    Zustand is designed to be extensible with custom hooks and middleware, allowing developers to enhance its functionality and integrate it with other libraries.

How to Choose: jotai vs mobx vs react-query vs recoil vs redux vs valtio vs xstate vs zustand

  • jotai:

    Choose Jotai if you prefer a minimalistic and atomic state management approach that allows for fine-grained control over state updates and is easy to integrate with existing React applications.

README for jotai


Jotai (light mode)


visit jotai.org or npm i jotai

Build Status Build Size Version Downloads Discord Shield Open Collective

Jotai scales from a simple useState replacement to an enterprise TypeScript application.

  • Minimal core API (2kb)
  • Many utilities and extensions
  • No string keys (compared to Recoil)

Examples: Demo 1 | Demo 2

First, create a primitive atom

An atom represents a piece of state. All you need is to specify an initial value, which can be primitive values like strings and numbers, objects, and arrays. You can create as many primitive atoms as you want.

import { atom } from 'jotai'

const countAtom = atom(0)
const countryAtom = atom('Japan')
const citiesAtom = atom(['Tokyo', 'Kyoto', 'Osaka'])
const mangaAtom = atom({ 'Dragon Ball': 1984, 'One Piece': 1997, Naruto: 1999 })

Use the atom in your components

It can be used like React.useState:

import { useAtom } from 'jotai'

function Counter() {
  const [count, setCount] = useAtom(countAtom)
  return (
    <h1>
      {count}
      <button onClick={() => setCount((c) => c + 1)}>one up</button>
      ...

Create derived atoms with computed values

A new read-only atom can be created from existing atoms by passing a read function as the first argument. get allows you to fetch the contextual value of any atom.

const doubledCountAtom = atom((get) => get(countAtom) * 2)

function DoubleCounter() {
  const [doubledCount] = useAtom(doubledCountAtom)
  return <h2>{doubledCount}</h2>
}

Creating an atom from multiple atoms

You can combine multiple atoms to create a derived atom.

const count1 = atom(1)
const count2 = atom(2)
const count3 = atom(3)

const sum = atom((get) => get(count1) + get(count2) + get(count3))

Or if you like fp patterns ...

const atoms = [count1, count2, count3, ...otherAtoms]
const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))

Derived async atoms needs suspense

You can make the read function an async function too.

const urlAtom = atom('https://json.host.com')
const fetchUrlAtom = atom(async (get) => {
  const response = await fetch(get(urlAtom))
  return await response.json()
})

function Status() {
  // Re-renders the component after urlAtom is changed and the async function above concludes
  const [json] = useAtom(fetchUrlAtom)
  ...

You can create a writable derived atom

Specify a write function at the second argument. get will return the current value of an atom. set will update the value of an atom.

const decrementCountAtom = atom(
  (get) => get(countAtom),
  (get, set, _arg) => set(countAtom, get(countAtom) - 1)
)

function Counter() {
  const [count, decrement] = useAtom(decrementCountAtom)
  return (
    <h1>
      {count}
      <button onClick={decrement}>Decrease</button>
      ...

Write only derived atoms

Just do not define a read function.

const multiplyCountAtom = atom(null, (get, set, by) =>
  set(countAtom, get(countAtom) * by),
)

function Controls() {
  const [, multiply] = useAtom(multiplyCountAtom)
  return <button onClick={() => multiply(3)}>triple</button>
}

Async actions

Just make the write function an async function and call set when you're ready.

const fetchCountAtom = atom(
  (get) => get(countAtom),
  async (_get, set, url) => {
    const response = await fetch(url)
    set(countAtom, (await response.json()).count)
  }
)

function Controls() {
  const [count, compute] = useAtom(fetchCountAtom)
  return (
    <button onClick={() => compute('http://count.host.com')}>compute</button>
    ...

Note about functional programming

Jotai's fluid interface is no accident β€” atoms are monads, just like promises! Monads are an established pattern for modular, pure, robust and understandable code which is optimized for change. Read more about Jotai and monads.

Links