В React-компонентах легко управлять локальным состоянием с помощью useState или useReducer. Но что, если нам нужно делиться состоянием между несколькими компонентами, часто находящимися в разных частях дерева? Вот здесь начинается настоящий вызов, который решается с помощью управления глобальным состоянием.
Сегодня мы разберём, зачем нужен Redux, его основные принципы, а также познакомимся с современными альтернативами. На практике создадим минимальное приложение для управления списком покупок с помощью Redux Toolkit.
Зачем нужен Redux?
Redux — это библиотека для управления состоянием приложения. Она помогает хранить глобальные данные, которые могут использоваться несколькими компонентами, и предоставляет удобные инструменты для работы с ними.
Проблемы, которые решает Redux:
- Пропс-дриллинг: Передача данных через несколько уровней компонентов.
 - Сложность синхронизации состояния: Когда одно и то же состояние изменяется из разных частей приложения.
 - Трудности с отладкой: Redux делает изменения состояния прозрачными и предсказуемыми.
 
Основные принципы Redux:
- Единый источник правды: Всё состояние приложения хранится в одном объекте — store.
 - Только для чтения: Состояние нельзя изменить напрямую. Единственный способ — отправить действие (action), описывающее изменение.
 - Чистые функции: Логика изменения состояния определяется редьюсерами — функциями, которые принимают текущее состояние и действие, а возвращают новое состояние.
 
Современные альтернативы Redux
Redux долгое время был стандартом для управления глобальным состоянием, но с развитием React появились более лёгкие и удобные решения. Вот некоторые из них:
Zustand
Минималистичная библиотека для управления состоянием.
Простая и понятная API: состояние создаётся через функции, без редьюсеров и экшенов.
Идеально для небольших и средних приложений.
Пример
import create from 'zustand';
const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));
Jotai
Библиотека атомарного состояния. Каждая часть состояния хранится в атоме, который можно подключать к компонентам.
Прямой доступ к состоянию, без промежуточных слоёв.
Пример
import { atom, useAtom } from 'jotai';
const countAtom = atom(0);
function Counter() {
  const [count, setCount] = useAtom(countAtom);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
React Query
Решение для работы с данными из API. Управляет кэшированием, синхронизацией и состоянием загрузки данных.
Лучше всего подходит для управления серверным состоянием.
Пример
import { useQuery } from 'react-query';
function Users() {
  const { data, isLoading } = useQuery('users', fetchUsers);
  if (isLoading) return <p>Загрузка...</p>;
  return <ul>{data.map((user) => <li key={user.id}>{user.name}</li>)}</ul>;
}
Почему всё ещё стоит изучать Redux?
- Мощность и гибкость: Подходит для сложных приложений.
 - Прозрачность: Легко отследить, что изменило состояние, благодаря экшенам и редьюсерам.
 - Экосистема: Большое сообщество, плагины и поддержка.
 
📢 Подписывайтесь на наш Telegram-канал.
Там вы найдете анонсы обучающих статей и видео, готовый код для ваших проектов и увлекательные курсы. Ничего лишнего — только практика, вдохновение и развитие.
С Redux Toolkit настройка и использование Redux стали проще, устранив многие недостатки оригинального Redux.
Практика: список покупок с Redux Toolkit
Создадим приложение, где пользователь может:
- Добавлять товары в список покупок.
 - Удалять товары из списка.
 - Просматривать текущий список.
 
Шаг 1: Установка Redux Toolkit
Убедитесь, что Redux Toolkit установлен:
npm install @reduxjs/toolkit react-redux
Шаг 2: Настройка Redux
Создаём файл store.js для хранения состояния:
import { configureStore, createSlice } from '@reduxjs/toolkit';
// Создаём slice (редьюсер и экшены)
const shoppingListSlice = createSlice({
  name: 'shoppingList',
  initialState: [],
  reducers: {
    addItem: (state, action) => {
      state.push(action.payload);
    },
    removeItem: (state, action) => {
      return state.filter((item, index) => index !== action.payload);
    },
  },
});
export const { addItem, removeItem } = shoppingListSlice.actions;
const store = configureStore({
  reducer: {
    shoppingList: shoppingListSlice.reducer,
  },
});
export default store;
Шаг 3: Подключение Redux к React
Оборачиваем приложение в Provider:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
Шаг 4: Компоненты приложения
Создаём компонент для списка покупок:
Компонент списка:
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { removeItem } from './store';
function ShoppingList() {
  const items = useSelector((state) => state.shoppingList);
  const dispatch = useDispatch();
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>
          {item}{' '}
          <button onClick={() => dispatch(removeItem(index))}>
            Удалить
          </button>
        </li>
      ))}
    </ul>
  );
}
export default ShoppingList;
Компонент добавления:
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { addItem } from './store';
function AddItem() {
  const [text, setText] = useState('');
  const dispatch = useDispatch();
  const handleSubmit = (e) => {
    e.preventDefault();
    if (text.trim()) {
      dispatch(addItem(text));
      setText('');
    }
  };
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Добавьте товар"
      />
      <button type="submit">Добавить</button>
    </form>
  );
}
export default AddItem;
Шаг 5: Объединяем компоненты
В App.jsx подключаем все компоненты:
import React from 'react';
import ShoppingList from './ShoppingList';
import AddItem from './AddItem';
function App() {
  return (
    <div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
      <h1>Список покупок</h1>
      <AddItem />
      <ShoppingList />
    </div>
  );
}
export default App;
Шаг 6: Запускаем проект
Запустите приложение:
npm start
Добавляйте товары, удаляйте их, и ваш список будет обновляться в реальном времени.
Итоги
Сегодня мы разобрали:
- Зачем нужен Redux: Для управления глобальным состоянием в сложных приложениях.
 - Современные альтернативы: Zustand, Jotai, React Query — для разных сценариев.
 - На практике создали приложение с Redux Toolkit.
 
Redux или альтернативы?
- Выберите Redux для сложных приложений.
 - Рассмотрите Zustand или Jotai для лёгких и средних задач.
 - Используйте React Query для работы с серверными данными.
 
Теперь вы можете уверенно выбирать инструменты для управления состоянием в ваших проектах.
                15.01.2025            
                0            
                942            
Комментарии
0