Рекомендации по управлению состоянием

Эффективное управление состоянием — ключ к поддерживаемому и читаемому коду в React Native. Ниже приведены основные рекомендации, которые помогут избежать распространённых ошибок и упростят развитие приложения.

Не храните вычисляемые данные в состоянии

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

Неправильно:

const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [fullName, setFullName] = useState(''); // избыточно

// При каждом изменении имени нужно обновлять fullName

Правильно:

const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');

const fullName = `${firstName} ${lastName}`; // вычисляется при рендере

Разделяйте локальное и глобальное состояние

  • Локальное состояние (useState, useReducer) — для данных, нужных только внутри одного компонента или экрана (например, текст в поле ввода, открытый аккордеон).
  • Глобальное состояние (useContext или внешние библиотеки) — для данных, используемых во многих частях приложения (тема, авторизация, настройки).

Не стоит «поднимать» состояние выше, чем это действительно необходимо. Излишнее использование контекста усложняет отладку и вызывает лишние перерисовки.

Передавайте функции через контекст осторожно

Контекст лучше использовать для передачи данных, а не поведения. Однако если вы всё же передаёте функции управления состоянием (например, toggleTheme), обязательно мемоизируйте их с помощью useCallback. Иначе каждый рендер провайдера будет создавать новую функцию, что приведёт к ненужным обновлениям всех потребителей контекста.

Пример правильного подхода:

const [darkMode, setDarkMode] = useState(false);

const toggleTheme = useCallback(() => {
  setDarkMode(prev => !prev);
}, []);

<ThemeContext.Provider value={{ darkMode, toggleTheme }}>

Минимизируйте количество состояний

Объединяйте связанные значения в один объект состояния, если они обновляются вместе:

// Лучше так
const [formState, setFormState] = useState({ email: '', password: '' });

// Чем так
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

Это особенно актуально при использовании useReducer, где структура состояния уже централизована.

Планируйте расширяемость

Даже если сейчас состояние простое, подумайте, как оно может измениться в будущем. Например, вместо булева флага isLoading иногда полезнее использовать строковый статус ('idle' | 'loading' | 'success' | 'error'), если возможны разные типы загрузки.

Следуя этим принципам, вы создадите приложение, в котором легко вносить изменения, находить ошибки и добавлять новые функции.