Что такое useState и как он работает?
useState — это один из основных хуков React, который позволяет добавлять локальное состояние в функциональные компоненты. До появления хуков, управлять состоянием можно было только в классовых компонентах с помощью this.state и this.setState(). useState сделал возможным использовать состояние внутри функций, что значительно упростило архитектуру и чтение кода.
Что делает useState
Когда вы вызываете useState, вы создаёте переменную состояния, которая сохраняет своё значение между перерендериваниями компонента. Вместе с этой переменной вы получаете функцию для её обновления. При вызове этой функции React:
-
сохраняет новое значение,
-
инициирует повторный рендер компонента с новым значением.
Синтаксис
const \[state, setState\] = useState(initialValue);
-
state — текущее значение состояния;
-
setState — функция, которая обновляет это значение;
-
initialValue — начальное значение (0, '', {}, [], true и т.д.).
Простой пример
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
export default function Counter() {
const \[count, setCount\] = useState(0);
return (
<View>
<Text>Счётчик: {count}</Text>
<Button title="Увеличить" onPress={() => setCount(count + 1)} />
</View>
);
}
-
count инициализируется как 0;
-
при нажатии кнопки вызывается setCount(count + 1);
-
компонент повторно рендерится, отображая обновлённое значение.
Как работает под капотом
-
При первом рендере React вызывает useState(0) и сохраняет 0 как начальное значение.
-
При каждом обновлении состояния с помощью setCount, React добавляет новое значение в очередь, затем повторно вызывает компонент с новым значением count.
React гарантирует, что значения, возвращаемые хуками, будут сохраняться между рендерами, благодаря механизму хранилища состояний, привязанного к порядку вызовов хуков.
Несколько состояний
Можно вызывать useState столько раз, сколько нужно:
const \[name, setName\] = useState('');
const \[age, setAge\] = useState(18);
const \[isOnline, setIsOnline\] = useState(false);
Каждое состояние независимо, React отслеживает их порядок и связывает значение с нужным вызовом.
Правила использования useState
-
useState можно вызывать только внутри функционального компонента или кастомного хука.
-
Нельзя вызывать useState:
-
внутри условий (if),
-
внутри циклов (for, map),
-
внутри вложенных функций или обработчиков.
-
-
Порядок вызова хуков должен быть одинаковым на каждом рендере, иначе React "путается", какое состояние к какому хуку относится.
Ленивая инициализация
Если начальное значение вычисляется сложно, можно использовать функцию:
const \[value, setValue\] = useState(() => {
console.log('Вычисление значения один раз');
return expensiveCalculation();
});
React вызовет эту функцию только при первом рендере, а не при каждом.
Обновление состояния
Прямое обновление:
setCount(count + 1);
Функциональное обновление (рекомендуется при зависимости от предыдущего состояния):
setCount(prevCount => prevCount + 1);
Это особенно важно при асинхронных событиях, когда вы не уверены, какое именно значение было на момент вызова setCount.
Обновление сложных объектов
Если вы храните в состоянии объект, нужно не мутировать его напрямую, а создавать новый:
const \[user, setUser\] = useState({ name: 'Алиса', age: 25 });
setUser(prev => ({
...prev,
age: prev.age + 1
}));
Почему? Потому что React сравнивает по ссылке, а не по значению. Только новый объект (новая ссылка) вызывает повторный рендер.
Обновление массивов
const \[items, setItems\] = useState(\[\]);
const addItem = (newItem) => {
setItems(prev => \[...prev, newItem\]);
};
Как и в случае с объектами, массивы тоже нужно копировать при обновлении.
Повторный рендер
Каждый раз при вызове setState, React перерисовывает весь компонент, чтобы отобразить актуальные данные.
-
Это не обновляет DOM напрямую — React сначала обновляет виртуальный DOM, затем сравнивает его с предыдущим состоянием и обновляет только изменённые элементы.
-
Перерисовка происходит асинхронно, React может объединять несколько setState вызовов для оптимизации.
Связь useState с TextInput
Хранение значения поля ввода:
const \[name, setName\] = useState('');
<TextInput
value={name}
onChangeText={setName}
/>
Каждое изменение текста вызывает setName, и value обновляется. Это называется управляемым компонентом.
Сброс значения
setName(''); // сбрасывает поле
Типы значений в useState
React допускает любые типы данных:
-
строки
-
числа
-
boolean
-
массивы
-
объекты
-
null, undefined
-
функции (если не ленивая инициализация, функция будет значением, а не вызовом)
Сравнение с this.state и this.setState (в классовых компонентах)
useState | this.state / this.setState | |
---|---|---|
Где используется | В функциональных компонентах | В классовых компонентах |
--- | --- | --- |
Инициализация | useState(initialValue) | this.state = { ... } в конструкторе |
--- | --- | --- |
Обновление | setState(newValue) | this.setState({ key: value }) |
--- | --- | --- |
Асинхронность | Да | Да |
--- | --- | --- |
Автоматическое слияние | Нет (нужно вручную объединять) | Да (объединяется автоматически) |
--- | --- | --- |
Сколько состояний | Неограниченно | Одно дерево состояния |
--- | --- | --- |
useState vs useReducer
Если вы работаете с сложной логикой, состоящей из многих переходов состояний, или вложенных структур, то предпочтительнее использовать useReducer.
Пример — корзина товаров, формы с валидацией, сложные сценарии переключения состояний.
Хуки и локальное состояние
-
Состояние, созданное с useState, привязано к конкретному экземпляру компонента.
-
Если компонент размонтируется, состояние уничтожается.
-
При новом монтировании — useState снова инициализируется.
useState — это фундаментальный хук, который позволяет управлять состоянием в React-функциях, делая их мощными и гибкими инструментами для построения интерактивных интерфейсов.