Jotai – Lightweight State Management

Loading

Jotai is a minimalist and lightweight state management library for React, designed with simplicity and performance in mind. It provides a straightforward API for managing both global and local state in React applications. Unlike more complex state management solutions like Redux or even Recoil, Jotai aims to provide an easy-to-use and low-overhead way to manage state, making it an excellent choice for smaller projects or for developers looking to avoid unnecessary boilerplate.

Jotai is based on atoms, which are units of state that can be shared and updated across components. It integrates well with React’s hooks and provides fine-grained control over component re-renders.


1. Installing Jotai

To start using Jotai in your React project, you need to install it via npm or yarn:

npm install jotai

Or with Yarn:

yarn add jotai

2. Basic Concepts in Jotai

Jotai follows a very simple and intuitive API. The two main concepts are:

  • Atoms: The basic unit of state in Jotai. Atoms represent state and can be used inside React components.
  • Providers: The provider wraps the application to make atoms accessible globally.

3. Creating Atoms in Jotai

Atoms are created using the atom function. Atoms store a piece of state and can be read and updated by any component in your app.

Here’s an example of creating a simple counter atom:

// store.js
import { atom } from 'jotai';

export const counterAtom = atom(0);

Explanation:

  • atom: The atom function creates an atom, which can hold a value. In this case, the counter starts at 0.

4. Using Atoms in Components

You can use atoms in your components using the useAtom hook. This hook provides the atom’s value and a function to update it.

Here’s an example of a simple counter component using Jotai:

// Counter.js
import React from 'react';
import { useAtom } from 'jotai';
import { counterAtom } from './store';

const Counter = () => {
  const [count, setCount] = useAtom(counterAtom);

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
};

export default Counter;

Explanation:

  • useAtom: This hook allows you to access the current state of the atom (count) and update it using the setCount function.
  • Component Re-renders: When the atom’s value changes, only the components that are subscribed to that atom will re-render.

5. Derived State with Atoms

Just like other state management libraries, Jotai allows you to derive state from existing atoms using read-only atoms. This can be useful for computed or dependent state.

For example, if you want to create a derived state that doubles the count value:

// store.js
import { atom } from 'jotai';

export const counterAtom = atom(0);
export const doubledCounterAtom = atom((get) => get(counterAtom) * 2);

Explanation:

  • doubledCounterAtom: This atom derives its value by reading from counterAtom and doubling it. The get function is used to read the value of another atom.

6. Using Derived Atoms in Components

You can use derived atoms the same way as normal atoms. Here’s how to use doubledCounterAtom:

// DoubledCounter.js
import React from 'react';
import { useAtom } from 'jotai';
import { doubledCounterAtom } from './store';

const DoubledCounter = () => {
  const [doubledCount] = useAtom(doubledCounterAtom);

  return <h2>Doubled Count: {doubledCount}</h2>;
};

export default DoubledCounter;

Explanation:

  • useAtom: The useAtom hook is used to read the value of doubledCounterAtom. This value is automatically updated when counterAtom changes.

7. Async Atoms in Jotai

Jotai also allows you to manage asynchronous state by creating atoms that represent async values. This is useful for tasks like data fetching.

Here’s an example of creating an atom that fetches data:

// store.js
import { atom } from 'jotai';

export const fetchDataAtom = atom(async (get) => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  const data = await response.json();
  return data;
});

Explanation:

  • Async Atom: The atom is asynchronous and will resolve the promise. Jotai will handle the promise lifecycle for you (i.e., loading, success, error states).

8. Using Async Atoms in Components

To use async atoms, you can use useAtom as well. The state will be updated once the async operation resolves.

// DataFetcher.js
import React, { useEffect } from 'react';
import { useAtom } from 'jotai';
import { fetchDataAtom } from './store';

const DataFetcher = () => {
  const [data, setData] = useAtom(fetchDataAtom);

  useEffect(() => {
    setData();  // Trigger the async fetch operation
  }, [setData]);

  if (!data) return <p>Loading...</p>;

  return (
    <div>
      <h2>Data:</h2>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default DataFetcher;

Explanation:

  • Async Data Handling: Jotai takes care of the async state transitions (loading, success) automatically. You can directly access the fetched data when it’s available.

9. Benefits of Using Jotai

  • Lightweight: Jotai is designed to be lightweight and minimal. It has no dependencies and provides just the essential tools to manage state.
  • Simplified API: The API is small and easy to understand, which reduces the learning curve for developers.
  • Scalable: While Jotai is small, it scales well for larger applications, especially as it lets you create atoms and manage state globally.
  • Reactivity: Only components using the updated atoms will re-render, leading to efficient updates in the app.
  • React Suspense and Concurrent Mode: Jotai works well with React’s Suspense and Concurrent Mode, making it suitable for modern React applications.
  • Flexible: Supports both synchronous and asynchronous states and derived states with minimal boilerplate.

Leave a Reply

Your email address will not be published. Required fields are marked *