Что такое «подъём состояния» (state lifting) в React?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Средний
#React

Краткий ответ

Подъём состояния — это техника в React, при которой состояние перемещается из дочерних компонентов в их общего родителя. Это позволяет нескольким компонентам совместно использовать и управлять одним и тем же состоянием. Подъём состояния необходим, когда несколько компонентов должны отображать одни и те же данные или когда дочерние компоненты должны взаимодействовать друг с другом.

Основные причины подъёма состояния:

  • Совместное использование данных — несколько компонентов нуждаются в одних и тех же данных
  • Коммуникация между компонентами — дочерние компоненты должны взаимодействовать
  • Единый источник истины — централизованное управление состоянием

Полный ответ

Подъём состояния — одна из фундаментальных концепций React, которая помогает управлять состоянием приложения на уровне родительских компонентов. Эта техника позволяет создавать более предсказуемый и поддерживаемый код.

Когда нужен подъём состояния

Подъём состояния необходим в следующих случаях:

1. Совместное использование данных

Когда несколько компонентов нуждаются в одних и тех же данных:

// Родительский компонент с поднятым состоянием
function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <CounterDisplay count={count} />
      <CounterButton onClick={() => setCount(count + 1)} />
    </div>
  );
}

2. Коммуникация между компонентами

Когда дочерние компоненты должны взаимодействовать:

// Родитель управляет состоянием обоих дочерних компонентов
function Form() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  
  return (
    <form>
      <NameInput value={name} onChange={setName} />
      <EmailInput value={email} onChange={setEmail} />
    </form>
  );
}

Практические примеры

Пример с счётчиком

// Без подъёма состояния - компоненты не синхронизированы
function BadExample() {
  return (
    <div>
      <Counter />
      <Counter />
    </div>
  );
}
 
// С подъёмом состояния - синхронизированное состояние
function GoodExample() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <Counter count={count} setCount={setCount} />
      <Counter count={count} setCount={setCount} />
    </div>
  );
}

Пример с формой

function UserForm() {
  const [userData, setUserData] = useState({
    name: '',
    email: '',
    age: ''
  });
  
  // Все поля формы управляются из одного состояния
}

Распространенные ошибки

1. Ненужный подъём состояния

// ❌ Подъём состояния, когда это не нужно
function Parent() {
  const [child1State, setChild1State] = useState('');
  const [child2State, setChild2State] = useState('');
  
  return (
    <div>
      <Child1 state={child1State} setState={setChild1State} />
      <Child2 state={child2State} setState={setChild2State} />
    </div>
  );
}
 
// ✅ Состояние остаётся в дочерних компонентах
function Parent() {
  return (
    <div>
      <Child1 />
      <Child2 />
    </div>
  );
}

2. Подъём всего состояния

// ❌ Подъём всего состояния дочернего компонента
function Parent() {
  const [childState, setChildState] = useState({
    localData: '',
    localPreference: '',
    localUIState: false
  });
  
  return <Child state={childState} setState={setChildState} />;
}
 
// ✅ Только необходимое состояние поднимается
function Parent() {
  const [sharedData, setSharedData] = useState('');
  
  return <Child sharedData={sharedData} setSharedData={setSharedData} />;
}

Лучшие практики

  1. Поднимайте только необходимое — не перемещайте всё состояние вверх
  2. Создавайте чистые интерфейсы — используйте понятные названия для props
  3. Избегайте глубокой вложенности — при глубокой иерархии используйте Context
  4. Разделяйте состояние по ответственности — каждая часть состояния должна иметь одну причину для изменения
  5. Используйте деструктуризацию — для удобной работы с поднятым состоянием

Совместимость

Подъём состояния — это стандартная практика React, которая работает во всех версиях библиотеки.

Ключевые преимущества подъёма состояния

  1. Единый источник истины — одно состояние управляет несколькими компонентами
  2. Синхронизация данных — все компоненты отображают актуальные данные
  3. Упрощённая отладка — состояние находится в одном месте
  4. Предсказуемость — поведение приложения становится более предсказуемым
  5. Удобство тестирования — проще тестировать компоненты с поднятым состоянием

Подъём состояния — важная техника для создания предсказуемого и поддерживаемого React-приложения, позволяющая эффективно управлять общим состоянием нескольких компонентов.


Задача для проверки знаний

Задача

В чём разница между этими двумя подходами и какой предпочтительнее?

// Подход 1: Состояние в дочерних компонентах
function Parent() {
  return (
    <div>
      <Input1 />
      <Input2 />
      <SubmitButton />
    </div>
  );
}
 
// Подход 2: Подъём состояния
function Parent() {
  const [value1, setValue1] = useState('');
  const [value2, setValue2] = useState('');
  
  return (
    <div>
      <Input1 value={value1} onChange={setValue1} />
      <Input2 value={value2} onChange={setValue2} />
      <SubmitButton 
        onSubmit={() => console.log({ value1, value2 })} 
      />
    </div>
  );
}
Посмотреть ответ

Ответ: Подход 2 (с подъёмом состояния) предпочтительнее.

Объяснение:

Подход 1 (без подъёма):

  • Каждый компонент Input управляет своим состоянием независимо
  • SubmitButton не имеет доступа к значениям из Input
  • Невозможно получить и отправить данные формы целиком
  • Компоненты не могут взаимодействовать друг с другом
  • Состояние разрознено, что усложняет управление

Подход 2 (с подъёмом состояния):

  • Родитель управляет всем состоянием формы
  • SubmitButton имеет доступ ко всем значениям
  • Можно легко получить и отправить все данные формы
  • Компоненты синхронизированы
  • Единый источник истины для данных формы
  • Упрощена валидация и обработка данных

Когда использовать каждый подход:

  • Подход 1 подходит для полностью независимых компонентов
  • Подход 2 необходим, когда компоненты должны взаимодействовать или когда родитель должен управлять данными дочерних компонентов

Подъём состояния особенно важен при работе с формами, фильтрами, сортировкой и другими сценариями, где несколько компонентов должны работать с общими данными.


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪