Топ-5 бібліотек для керування станом у React

React

Керування станом у React — одна з ключових тем для розробників, оскільки додатки стають дедалі складнішими, а їхня архітектура потребує продуманих рішень. Незважаючи на вбудований useState і useReducer, у багатокомпонентних додатках часто виникає необхідність централізованого керування станом. У цій статті ми розглянемо топ-5 бібліотек для керування станом у React, їхні особливості, переваги та коли їх варто використовувати.

1. Redux – класика глобального стану

🌟 Коли використовувати:

  • Великі проєкти, де важливо зберігати та контролювати зміни стану.
  • Коли потрібен суворий контроль над даними та можливість відстеження змін.
  • Коли є багато взаємопов’язаних компонентів, які потребують доступу до спільного стану.

🔹 Основні особливості:

  • Централізований стор (store) – весь стан зберігається в єдиному сховищі.
  • Чисті редюсери – зміни вносяться через функції, що не змінюють поточний стан напряму.
  • Middleware (наприклад, redux-thunk або redux-saga) дозволяють керувати асинхронними запитами.

🔸 Мінуси:

  • Велика кількість “бойлерплейту” (багато коду навіть для простих операцій).
  • Висока складність для новачків.

🔹 Приклад Redux у дії:

// store.js
import { createStore } from 'redux';

const initialState = { count: 0 };

const counterReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

const store = createStore(counterReducer);
export default store;
// CounterComponent.js
import { useSelector, useDispatch } from 'react-redux';

const CounterComponent = () => {
  const count = useSelector((state) => state.count);
  const dispatch = useDispatch();

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </div>
  );
};

2. Zustand – мінімалістичний стейт-менеджер

🌟 Коли використовувати:

  • Коли потрібна легка альтернатива Redux без зайвого коду.
  • Коли ви хочете керувати станом без громіздких редюсерів.
  • Ідеально підходить для невеликих проєктів або управління локальним станом.

🔹 Основні особливості:

  • Простий API, що не вимагає створення редюсерів.
  • Підтримка асинхронних дій без middleware.
  • Прямий доступ до стану без потреби в селекторах чи провайдерах.

🔸 Мінуси:

  • Менша екосистема, ніж у Redux.
  • Може бути не найкращим вибором для великих додатків.

🔹 Приклад використання:

import create from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

const CounterComponent = () => {
  const { count, increment, decrement } = useStore();

  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
};

3. Recoil – нативний стейт-менеджер від Meta

🌟 Коли використовувати:

  • Коли потрібна потужна альтернатива Redux з меншими витратами.
  • Для проєктів, які працюють з деревоподібними структурами стану.

🔹 Основні особливості:

  • Використання атомів (мінімальних одиниць стану).
  • Асинхронні селектори, що дозволяють легко працювати з даними з API.
  • Глибока інтеграція з React Suspense.

🔸 Мінуси:

  • Поки що перебуває у фазі розробки та не є стандартом.
  • Деякі особливості не підтримуються старими версіями React.

🔹 Приклад використання:

import { atom, useRecoilState } from 'recoil';

// Створюємо атом (маленький шматочок стану)
const countState = atom({
  key: 'countState',
  default: 0,
});

const CounterComponent = () => {
  const [count, setCount] = useRecoilState(countState);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  );
};

4. Jotai – суперлегкий та реактивний стейт-менеджер

🌟 Коли використовувати:

  • Для невеликих проєктів, які потребують гнучкого керування станом.
  • Коли хочете щось простіше, ніж Recoil, але з подібною концепцією.

🔹 Основні особливості:

  • Прямий доступ до стану без складної структури.
  • Використання атомів (як у Recoil).
  • Нативна підтримка асинхронних операцій.

🔸 Мінуси:

  • Менша підтримка в спільноті.
  • Потребує глибшого розуміння реактивних структур.

🔹 Приклад використання:

import { atom, useAtom } from 'jotai';

const countAtom = atom(0);

const CounterComponent = () => {
  const [count, setCount] = useAtom(countAtom);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  );
};

5. React Query – для роботи з серверним станом

🌟 Коли використовувати:

  • Коли потрібно ефективно працювати з запитами до API.
  • Якщо додаток потребує кешування даних і оновлення при зміні бекенду.

🔹 Основні особливості:

  • Автоматичне кешування даних.
  • Фонове оновлення при зміні фокусу або повторних запитах.
  • Мінімізація запитів до сервера.

🔸 Мінуси:

  • Використовується для роботи зовнішніх даних, а не локального стану.

🔹 Приклад використання:

import { useQuery } from '@tanstack/react-query';

const fetchUsers = async () => {
  const res = await fetch('https://jsonplaceholder.typicode.com/users');
  return res.json();
};

const UsersList = () => {
  const { data, error, isLoading } = useQuery(['users'], fetchUsers);

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading users</p>;

  return (
    <ul>
      {data.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

Обирайте бібліотеку відповідно до завдань вашого проєкту! 🚀