Гайд по React Native для собеседований: разбор реальных сценариев, примеры кода и глубокие объяснения. Начни готовиться сейчас!
Большинство блогов по подготовке кидают в вас определениями: «Компонент — это переиспользуемая часть UI». С таким ответом вас не возьмут. Настоящие собеседования — не тест на словарный запас. Интервьюер описывает ситуацию — приложение тормозит, список слишком часто перерисовывается, экран зависает — и смотрит, как вы мыслите. Он хочет понять, почему что-то работает, а не как это называется.
Этот гайд написан вокруг реальных сценариев. Каждый вопрос — то, что реально спрашивают в продуктовых компаниях, стартапах и аутсорсе. Каждый ответ начинается с простого, а затем углубляется до уровня, способного впечатлить сеньора.
Читайте медленно, проговаривайте ответы вслух. К концу вы не просто запомните ответы — вы поймёте React Native.
Когда пользователь покидает приложение, ОС может перевести его в фоновый режим, а при нехватке памяти — полностью завершить процесс. Если данные формы хранились только в состоянии компонента (useState в памяти), они исчезают вместе с процессом.
Исправление зависит от данных:
Сеньорный уровень: Различайте ре-рендер (дешёвый, частый — состояние сохраняется), размонтирование (компонент покинул дерево — его состояние пропадает, если не поднято или не сохранено) и завершение процесса (ОС убила приложение — выживают только сохранённые данные). Большинство багов с потерей данных возникают из-за путаницы между этими понятиями. Тестируйте завершение процесса, убивая приложение из фона.
React Native предоставляет состояние приложения через AppState с тремя значениями:
(На Android inactive фактически не используется так же; в основном вы видите active и background.)
При входящем звонке: приложение переходит в inactive (UI звонка прерывает его на iOS); если пользователь уходит из приложения для ответа на звонок, оно переходит в background.
Ключевое правило: сохраняйте состояние и приостанавливайте работу (таймеры, видео, геолокацию) при background/inactive; возобновляйте при active. Подписывайтесь через AppState.addEventListener('change', handler) и отписывайтесь при размонтировании.
props — данные, передаваемые в компонент от родителя. Они доступны только для чтения внутри дочернего компонента — он отображает или использует их, но не изменяет. Используйте props для настройки компонента: Button получает title и onPress.
state — данные, принадлежащие и управляемые компонентом, которые могут меняться со временем, вызывая ре-рендер. Используйте state для вещей, изменяющихся в результате взаимодействия или данных: вкл/выкл тумблера, ввод формы, статус загрузки.
Реальный пример: PriceTag, который просто показывает переданную цену — только props. LikeButton, который переключается между заполненным и пустым при нажатии — state для флага лайка.
Нюанс для сеньора: «Данные текут вниз» — родители передают props детям; дети сообщают наверх через колбэки. Поднятие состояния на правильный уровень (и его недублирование) — ключевой навык. Чрезмерное использование локального state для общих данных ведёт к prop-drilling и багам.
useEffect выполняет побочные эффекты в функциональных компонентах — вещи вне чистого рендеринга: подписки, таймеры, сетевые вызовы, обработчики событий. Он запускается после рендера, а массив зависимостей контролирует, когда он перезапускается.
Очистка: верните функцию из эффекта — React вызывает её при размонтировании и перед повторным запуском эффекта. Отписывайтесь/очищайте таймеры здесь.
useEffect(() => {
const sub = AppState.addEventListener('change', onChange);
return () => sub.remove(); // очистка при размонтировании
}, []);
Правило, которое любят интервьюеры: что настроили в эффекте — то и отключайте в очистке. Забытая очистка приводит к утечкам подписок/таймеров и багам «обновление состояния на размонтированном компоненте».
Массив зависимостей указывает React, когда перезапускать эффект — он перезапускается при изменении любого перечисленного значения. Три случая: [] (один раз), [a, b] (при изменении a или b) и отсутствие массива (после каждого рендера).
Самая частая ошибка — stale closures / пропущенные зависимости: если эффект использует значение (проп, состояние или функцию), но вы не указали его в зависимостях, эффект захватывает старое (устаревшее) значение и никогда не обновляется — например, setInterval, который всегда логирует начальное значение. И наоборот, указание нестабильного значения (функции/объекта, создаваемого заново при каждом рендере) в зависимостях приводит к постоянному перезапуску эффекта (бесконечный цикл переподписок).
Исправления: включайте все используемые значения и стабилизируйте функции/объекты с помощью useCallback/useMemo, чтобы они не меняли идентичность при каждом рендере. Правило ESLint react-hooks/exhaustive-deps ловит пропущенные зависимости. Объяснение stale closures — сильный сеньорный сигнал.
React хранит лёгкое in-memory дерево, описывающее ваш UI (виртуальное дерево). При изменении состояния/пропов React строит новое дерево и сравнивает его со старым (согласование), чтобы вычислить минимальный набор изменений, а затем применяет только их.
В React Native нет браузерного DOM — вместо этого React согласует дерево компонентов и отправляет минимальные обновления на нативную сторону, которая обновляет реальные нативные вью (UIView/ViewGroup). Та же идея сравнения, но вывод — нативные вью, а не HTML.
Почему это важно: поэтому важны ключи в списках (они помогают сравнению правильно сопоставлять элементы) и почему лишние ре-рендеры — это лишняя работа: React всё равно должен их согласовать. Понимание согласования лежит в основе большинства ответов по производительности.
Контролируемый — значение компонента управляется состоянием. TextInput получает значение из state, а onChangeText обновляет этот state. React — единый источник истины:
<TextInput value={text} onChangeText={setText} />
Неконтролируемый — компонент управляет своим внутренним значением; вы читаете его только когда нужно (например, через ref). React не управляет каждым нажатием клавиши.
Компромисс: контролируемые входы дают полный контроль (валидация, форматирование, синхронизация), но вызывают ре-рендер при каждом нажатии; неконтролируемые легче, но их сложнее контролировать. Сценарий: форма с живой валидацией → контролируемый. Простой ввод, где нужно только финальное значение → неконтролируемый (ref) может избежать ре-рендеров на каждое нажатие. Знание этого компромисса показывает реальный опыт работы с формами.
Задержка — это время запуска: нативное приложение запускается, движок JS (Hermes) загружает и парсит ваш JS-бандл, и React рендерит первый экран. Выполнение тяжёлой синхронной работы при запуске увеличивает задержку.
Причины и исправления:
Сеньорный момент: «Измеряйте с помощью Flipper / профайлера перед оптимизацией» и упомяните Hermes + inline requires как самые большие выигрыши в скорости запуска. Это показывает актуальные практические знания.
Зависит от направления и области видимости:
Почему не глобальная переменная / мутируемый модуль: это создаёт скрытую связанность, сложно тестируется и не вызывает ре-рендеры. Параметры навигации (явные) или ограниченное состояние (общее) — чистые варианты.
Вызов сеттера состояния (например, setCount(1)) делает две вещи: он планирует обновление с новым значением и помечает компонент для ре-рендера. При следующем рендере useState возвращает новое значение, и React согласует новый вывод со старым для обновления нативных вью.
Ключевые детали, которые проверяют интервьюеры:
Знание батчинга и функционального обновлятора — очень частый практический вопрос.
useState идеален для локального, эфемерного состояния внутри одного компонента. Но по мере роста приложения вы сталкиваетесь с ограничениями:
Поэтому нужны способы совместного использования состояния (Context, Redux, Zustand) и специализированные инструменты для серверного состояния (React Query). Формулировка проблемы перед называнием решений — сеньорный подход, и она задаёт различие между клиентским и серверным состоянием, что является главной темой 2026 года.
ОС освобождает память, незаметно убивая фоновые приложения. Чтобы вернуть пользователя, объедините уровни:
Сеньорный момент: «Не полагайтесь только на componentWillUnmount — процесс может быть убит без его вызова. Сохраняйте проактивно, а не только при выходе».
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →