jotai vs recoil vs react-tracked vs unstated-next
State Management Libraries for React Comparison
1 Year
jotairecoilreact-trackedunstated-nextSimilar Packages:
What's State Management Libraries for React?

State management libraries for React provide mechanisms to manage and share state across components in a predictable way. They help developers maintain a clear flow of data and state changes, which is crucial for building scalable and maintainable applications. Each library has its own approach to state management, catering to different needs such as simplicity, performance, and reactivity. Choosing the right library can significantly impact the development experience and application performance.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
jotai1,341,04119,513497 kB69 days agoMIT
recoil562,16819,6392.21 MB3242 years agoMIT
react-tracked148,9472,77937.3 kB16 months agoMIT
unstated-next38,878---6 years agoMIT
Feature Comparison: jotai vs recoil vs react-tracked vs unstated-next

State Management Approach

  • jotai:

    Jotai uses atomic state management, allowing you to create small, independent pieces of state that can be composed together. This results in a more modular approach, where components can subscribe to only the state they need, improving performance and reducing unnecessary re-renders.

  • recoil:

    Recoil introduces a more sophisticated model with atoms and selectors. Atoms represent pieces of state, while selectors derive state based on atoms. This allows for complex state relationships and derived state management, making it suitable for larger applications with intricate state needs.

  • react-tracked:

    React-tracked provides a context-based approach to state management. It leverages React's context API to create a subscription model, allowing components to re-render only when the specific part of the state they depend on changes, thus optimizing performance while maintaining simplicity.

  • unstated-next:

    Unstated-next offers a simple and lightweight approach to state management using React hooks. It allows you to create containers that encapsulate state and logic, making it easy to share state across components without the overhead of a more complex library.

Learning Curve

  • jotai:

    Jotai has a gentle learning curve, especially for developers familiar with React hooks. Its API is straightforward, making it easy to integrate into existing projects without significant overhead or complexity.

  • recoil:

    Recoil has a moderate learning curve due to its unique concepts like atoms and selectors. While it provides powerful features, understanding its architecture may take some time for developers new to state management in React.

  • react-tracked:

    React-tracked is designed to be simple and intuitive, leveraging existing React patterns. Developers familiar with context and hooks will find it easy to adopt, making it a good choice for those new to state management.

  • unstated-next:

    Unstated-next is very easy to learn, especially for those who are already comfortable with React hooks. Its simplicity and minimal API make it a great choice for quick adoption in smaller projects.

Performance

  • jotai:

    Jotai is optimized for performance as it minimizes re-renders by allowing components to subscribe to specific atoms. This granular control over state leads to efficient updates and better overall performance in applications.

  • recoil:

    Recoil's architecture allows for efficient state updates and derived state management, which can lead to better performance in complex applications. However, careful management of atoms and selectors is necessary to avoid performance pitfalls.

  • react-tracked:

    React-tracked enhances performance by ensuring that components only re-render when the specific part of the state they depend on changes. This reduces unnecessary renders and improves responsiveness in larger applications.

  • unstated-next:

    Unstated-next is lightweight and performs well in most scenarios, but it may not be as optimized for large-scale applications compared to more complex libraries. It is best suited for simpler use cases where performance is not a critical concern.

Extensibility

  • jotai:

    Jotai is highly extensible, allowing developers to create custom atoms and hooks. This flexibility makes it suitable for a wide range of applications, from simple to complex state management needs.

  • recoil:

    Recoil's architecture supports extensibility through its atoms and selectors, enabling developers to build complex state relationships and derived state logic. This makes it a powerful choice for large applications with evolving state needs.

  • react-tracked:

    React-tracked is designed to be extensible through its context-based model. Developers can create custom providers to encapsulate state logic, allowing for reusable state management patterns across applications.

  • unstated-next:

    Unstated-next is simple and extensible, allowing for easy integration of additional logic within containers. However, its simplicity may limit its use in more complex state management scenarios.

Community and Ecosystem

  • jotai:

    Jotai has a growing community and ecosystem, with increasing adoption among developers. Its minimalistic approach appeals to those looking for a lightweight state management solution.

  • recoil:

    Recoil benefits from strong backing by the React team and has a vibrant community. Its feature set and performance optimizations make it a popular choice for larger applications, leading to a rich ecosystem of resources and tools.

  • react-tracked:

    React-tracked has a smaller community compared to others but is gaining traction due to its simplicity and effectiveness. It is well-suited for developers looking for a straightforward solution without the complexity of larger libraries.

  • unstated-next:

    Unstated-next has a smaller community but is appreciated for its simplicity and ease of use. It is a good choice for smaller projects or teams looking for a straightforward state management solution.

How to Choose: jotai vs recoil vs react-tracked vs unstated-next
  • jotai:

    Choose Jotai if you prefer a minimalistic approach to state management with a focus on atomic state. It is ideal for projects where you want to manage state in a granular way, allowing for better performance and easier debugging.

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