← Назад ко всем вопросам

Разница между локальным состоянием (useState/useReducer) и состоянием, которое выносится в контекст или стейт-менеджер

1️⃣ Как кратко ответить

Локальное состояние (useState/useReducer) управляет состоянием на уровне отдельного компонента и используется для данных, которые не нужно делиться между компонентами. Состояние, вынесенное в контекст или стейт-менеджер, используется для управления состоянием, которое должно быть доступно нескольким компонентам или всему приложению, обеспечивая централизованное управление и упрощая обмен данными.

2️⃣ Подробное объяснение темы

В React управление состоянием — это ключевая концепция, которая определяет, как данные управляются и передаются между компонентами. Существует несколько подходов к управлению состоянием, и выбор между локальным состоянием и состоянием, вынесенным в контекст или стейт-менеджер, зависит от потребностей приложения.

Локальное состояние

Локальное состояние управляется на уровне отдельного компонента с помощью хуков useState или useReducer.

  • useState: используется для управления простыми состояниями, такими как строки, числа или объекты.
import React, { useState } from 'react';
​
function Counter() {
  // Инициализация состояния с начальным значением 0
  const [count, setCount] = useState(0);
​
  // Функция для увеличения счетчика
  const increment = () => {
    setCount(count + 1);
  };
​
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
  • useReducer: используется для более сложных состояний или когда требуется логика обновления состояния, напоминающая редюсеры в Redux.
import React, { useReducer } from 'react';
​
// Определение редюсера с действиями для изменения состояния
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}
​
function Counter() {
  // Инициализация состояния с редюсером и начальным значением
  const [state, dispatch] = useReducer(reducer, { count: 0 });
​
  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

Состояние, вынесенное в контекст или стейт-менеджер

Когда состояние должно быть доступно нескольким компонентам или всему приложению, его можно вынести в контекст или использовать стейт-менеджер, такой как Redux или MobX.

  • Контекст (Context API): позволяет передавать данные через дерево компонентов без необходимости передавать пропсы на каждом уровне.
import React, { createContext, useContext, useState } from 'react';
​
// Создание контекста
const CountContext = createContext();
​
function CountProvider({ children }) {
  const [count, setCount] = useState(0);
​
  return (
    // Предоставление значения контекста
    <CountContext.Provider value={{ count, setCount }}>
      {children}
    </CountContext.Provider>
  );
}
​
function Counter() {
  // Использование контекста
  const { count, setCount } = useContext(CountContext);
​
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
​
function App() {
  return (
    <CountProvider>
      <Counter />
    </CountProvider>
  );
}
  • Стейт-менеджеры (например, Redux): обеспечивают централизованное управление состоянием с помощью глобального хранилища, что упрощает управление сложными состояниями и их синхронизацию между компонентами.
// Пример использования Redux
import { createStore } from 'redux';
import { Provider, useDispatch, useSelector } from 'react-redux';
​
// Определение редюсера
function counterReducer(state = { count: 0 }, 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);
​
function Counter() {
  // Получение состояния и диспетчера из Redux
  const count = useSelector((state) => state.count);
  const dispatch = useDispatch();
​
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}
​
function App() {
  return (
    <Provider store={store}>
      <Counter />
    </Provider>
  );
}

Зачем это нужно

Локальное состояние подходит для управления состоянием, специфичным для одного компонента, что упрощает его использование и понимание. Однако, когда состояние должно быть доступно нескольким компонентам, использование контекста или стейт-менеджера позволяет избежать "проброса" пропсов через несколько уровней и обеспечивает более чистую и поддерживаемую архитектуру приложения.

Тема: React
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки