Вопросы на собеседовании: React Native-разработчик
100 реальных вопросов с образцовыми ответами и пояснениями для уровня Junior React Native разработчик.
Смотреть пример резюме: React Native-разработчик →Тренировка флешкарточками
Интервальное повторение · Hunter Pass
Вопросы
React Native использует концепции React, но рендерит представления мобильных платформ вместо браузерного HTML.
- Я работаю с View, Text и Pressable вместо элементов div, p и button.
- Стили задаются JavaScript-объектами с подмножеством возможностей CSS, а не браузерной таблицей стилей с селекторами и каскадом CSS.
- Я также учитываю safe area, кнопку «Назад» на Android, разрешения и сенсорный ввод.
Зачем это спрашивают: Интервьюер проверяет, умеет ли кандидат переносить знания React, не считая мобильное приложение сайтом в оболочке.
React Native требует помещать текстовые строки внутрь Text, а наследование текстовых стилей работает только в поддереве Text.
- Строка непосредственно внутри View недопустима, поэтому перед выводом я оборачиваю её в Text.
- Вложенный Text наследует от родительского Text цвет, семейство и размер шрифта, если не переопределяет их.
- Стили View не переходят к дочернему Text, поэтому общую типографику нужно задать родительскому Text или передать явно.
Зачем это спрашивают: Интервьюер проверяет особые правила вывода и наследования текста, а не ещё одно сопоставление HTML-тегов с нативными компонентами.
JSX служит синтаксисом для описания дерева React-элементов внутри JavaScript или TypeScript.
- Перед запуском приложения сборщик преобразует JSX в вызовы создания React-элементов.
- Теги вроде View могут ссылаться на импортированные компоненты, а строчные HTML-теги вроде div не являются примитивами React Native.
- JavaScript-выражения помещаются в фигурные скобки, например source={{ uri: avatarUrl }} или {name}.
Зачем это спрашивают: Интервьюер оценивает, понимает ли кандидат JSX как синтаксис компонентов, а не браузерную разметку.
Переданный родителем label является prop, а изменяющийся count хранится в state.
- Props служат входными данными только для чтения, поэтому дочерний компонент не должен присваивать им новый label.
- useState(0) хранит текущее значение count, а его setter запрашивает обновление.
- Если count должен контролировать родитель, я передам count и callback onChange вместо дублирования состояния.
Зачем это спрашивают: Интервьюер проверяет, отделяет ли кандидат внешние входные данные от изменяемых данных самого компонента.
Обновление состояния запланирует новый рендер компонента и сверку нового дерева с предыдущим.
- Функция компонента запустится снова и прочитает обновлённое значение count.
- React сравнит деревья элементов и применит только необходимые изменения нативных представлений.
- Рендер должен оставаться чистым, поэтому сетевые запросы и подписки размещаются в эффектах или обработчиках событий, а не в теле компонента.
Зачем это спрашивают: Интервьюер проверяет базовую ментальную модель обновления состояния, рендера и применения изменений нативного UI.
Я бы описал переиспользуемые стили через StyleSheet.create и объединил их в массиве с условным стилем.
- StyleSheet.create создаёт именованные объекты стилей, например styles.card и styles.selectedCard.
- Компонент может использовать style={[styles.card, selected && styles.selectedCard]}.
- Более поздние элементы переопределяют совпадающие свойства, поэтому selectedCard может менять только borderColor или backgroundColor.
Зачем это спрашивают: Интервьюер проверяет, умеет ли кандидат создавать переиспользуемые стили и предсказуемо применять локальные переопределения.
Я бы использовал горизонтальный контейнер и задал обеим обёрткам кнопок flex: 1.
- Контейнеру нужен flexDirection: 'row', потому что в React Native по умолчанию используется направление column.
- Каждая обёртка с flex: 1 получит равную долю доступной ширины.
- Свойство gap: 12 у контейнера создаст нужный интервал без отступов у каждой отдельной кнопки.
Зачем это спрашивают: Интервьюер оценивает практическое знание Flexbox, особенно направление column по умолчанию в React Native.
Числа раскладки React Native задаются в логических единицах, независимых от плотности, а не в физических пикселях.
- Платформы преобразуют 100 единиц раскладки в разное число физических пикселей согласно плотности экрана.
- Благодаря этому элемент сохраняет примерно одинаковый физический размер на разных устройствах.
- Я использую PixelRatio только там, где действительно нужны данные о плотности пикселей, а не умножаю вручную каждое значение раскладки.
Зачем это спрашивают: Интервьюер проверяет, понимает ли кандидат плотность экрана без жёсткой привязки размеров к отдельным устройствам.
Я бы оставил один компонент и выбрал только платформенное значение через API Platform.
- Platform.select может вернуть { padding: 16 } для ios и { padding: 12 } для android.
- Platform.OS подходит для небольшого условия с простыми ветками.
- Если различается вся реализация, файлы Card.ios.tsx и Card.android.tsx могут иметь общий путь импорта.
Зачем это спрашивают: Интервьюер проверяет, умеет ли кандидат изолировать небольшие платформенные различия и сохранять общий код.
Я бы получил отступы safe area и добавил нужное верхнее или нижнее пространство вокруг содержимого экрана.
- react-native-safe-area-context предоставляет SafeAreaView и useSafeAreaInsets для актуальной кроссплатформенной обработки.
- Я применяю только нужные дизайну края, чтобы вложенные навигаторы не добавляли один отступ дважды.
- Я проверяю экран на iPhone с вырезом и Android с жестовой навигацией, потому что их отступы могут различаться.
Зачем это спрашивают: Интервьюер проверяет, учитывает ли кандидат физические вырезы и системный UI вместо фиксированного отступа наугад.
Я бы описал тип props с обязательными строкой и числом и необязательной функцией.
- Форма может содержать uri: string, size: number и onPress?: () => void.
- Параметр компонента типизируется как AvatarProps, поэтому некорректный вызов не пройдёт проверку типов.
- Значение size по умолчанию имеет смысл только после превращения size в необязательное поле; обязательному prop не нужен скрытый fallback.
Зачем это спрашивают: Интервьюер оценивает базовое моделирование обязательных, необязательных и callback props в TypeScript.
Я бы хранил количество в useState и обновлял его функциональной формой setter.
- const [quantity, setQuantity] = useState(1) даёт текущее значение и функцию обновления.
- Увеличение использует setQuantity(current => current + 1), что безопасно при постановке обновлений в очередь.
- Уменьшение использует Math.max(1, current - 1), поэтому ограничение состояния соблюдается внутри обновления.
Зачем это спрашивают: Интервьюер проверяет базовую работу с локальным состоянием и безопасные обновления на основе предыдущего значения.
Я бы запускал запрос в эффекте, зависящем от userId, и не позволял устаревшему запросу обновлять состояние.
- Массив зависимостей содержит userId, поэтому переход с 42 на другого пользователя запускает новый запрос.
- AbortController может отменить fetch в cleanup при размонтировании компонента или изменении userId.
- Я веду loading и error state вокруг запроса, а не делаю саму функцию эффекта async.
Зачем это спрашивают: Интервьюер оценивает зависимости эффекта, cleanup и базовую безопасность асинхронного состояния.
useMemo может переиспользовать результат фильтрации, а useCallback сохраняет ссылку onSelect для мемоизированных строк.
- useMemo заново фильтрует 500 элементов только при изменении исходного массива или текста фильтра.
- useCallback возвращает ту же ссылку на onSelect, пока его зависимости не изменились, поэтому React.memo не перерисует строку только из-за нового обработчика.
- Я добавлю эти хуки после профилирования: фильтрация 500 простых элементов может быть дешёвой, а мемоизация усложняет код и тоже требует работы.
Зачем это спрашивают: Интервьюер проверяет, понимает ли кандидат назначение каждого хука и применяет ли мемоизацию только при измеримой пользе.
Я бы связал значение TextInput с состоянием и обновлял его через onChangeText.
- value={email} делает React state источником истины для отображаемого текста.
- onChangeText={setEmail} сохраняет каждое изменение без чтения браузерного объекта события.
- После успешной отправки я вызываю setEmail(''), а после ошибки сохраняю текст пользователя для исправления.
Зачем это спрашивают: Интервьюер оценивает паттерн контролируемого поля и разумное поведение мобильной формы при отправке.
Я бы передал функцию, которая вызовет save с id 7 при нажатии.
- onPress={() => saveItem(7)} передаёт callback, а не результат saveItem.
- Запись onPress={saveItem(7)} выполнит функцию во время рендера и передаст в onPress возвращённое значение.
- Если обработчику нужны координаты нажатия, его аргумент event содержит nativeEvent, но id элемента берётся из замыкания или props.
Зачем это спрашивают: Интервьюер проверяет понимание ссылок на callback, замыканий и нативных объектов событий.
Я бы обрабатывал состояния в понятном порядке приоритетов через ранние возвраты или одну явную ветку.
- Во время loading показывается ActivityIndicator, чтобы пустой массив не выглядел как завершённое пустое состояние.
- При ошибке показывается сообщение и действие для повторной попытки.
- После успешной загрузки рендерится либо пустое состояние, либо список данных в зависимости от items.length.
Зачем это спрашивают: Интервьюер оценивает, умеет ли кандидат делать взаимоисключающие состояния UI понятными и корректными.
Стабильный id сообщения позволяет React связывать отрендеренную строку с тем же сообщением после переупорядочивания.
- Индекс массива меняется при вставке или перемещении сообщения, поэтому локальное состояние строки может перейти к другому элементу.
- keyExtractor={item => item.id} даёт FlatList стабильный строковый ключ.
- id должен быть уникальным среди соседних элементов; случайные ключи тоже плохи, потому что заставляют строки перемонтироваться при каждом рендере.
Зачем это спрашивают: Интервьюер проверяет, понимает ли кандидат ключи как стабильную идентичность, а не способ убрать предупреждение.
Я бы оставил общую визуальную оболочку внутри Card, а переменное содержимое передавал через props или children.
- children позволяет каждому экрану поместить собственные Text, Image или форму внутрь одной оболочки карточки.
- Именованные props вроде footer или onPress могут явно описать общие слоты действий.
- Это устраняет копирование стилей и не связывает Card с загрузкой данных или навигацией конкретного экрана.
Зачем это спрашивают: Интервьюер оценивает, умеет ли кандидат переиспользовать UI через композицию вместо одного перегруженного условного компонента.
Error boundary может заменить сломанное дочернее дерево запасным UI вместо потери всего экрана.
- Он ловит ошибки рендера и lifecycle ниже своей границы, поэтому я размещаю его вокруг экрана или рискованного поддерева.
- Базовый boundary по-прежнему реализуется классовым компонентом с lifecycle-методами ошибок либо берётся из проверенной библиотеки.
- Он не ловит ошибки обработчиков событий и отклонённые async-операции, для которых нужен обычный try и catch.
Зачем это спрашивают: Интервьюер проверяет практическую область действия и ограничения React error boundaries.
Закрытые вопросы
- 21
Почему для checkout из 3 экранов Cart, Address и Payment подойдёт stack navigator?
navigation - 22
У приложения есть 4 главных раздела Home, Search, Saved и Profile; когда для них подходит tab navigator?
navigation - 23
Как ProductList должен открыть ProductDetails с productId 42 и безопасно прочитать этот параметр?
- 24
Корневой stack содержит навигатор HomeTabs; как уведомлению открыть экран Settings внутри вложенных вкладок?
android-components - 25
Что нужно настроить, чтобы URL myapp://product/42 открывал ProductDetails для товара 42?
config - 26
Экран вкладки остаётся смонтированным, пока открыта другая вкладка; как запускать аналитику при каждом получении фокуса?
- 27
На Android форма с несохранёнными изменениями должна запросить подтверждение перед уходом по одному нажатию аппаратной кнопки «Назад»; как это сделать?
forms - 28
В форме регистрации из 6 полей последнее поле скрывается клавиатурой; какую базовую раскладку стоит попробовать сначала?
formsui - 29
Кнопка только с иконкой удаляет одну фотографию; какие accessibility role и label ей нужны?
mobile-accessibilitya11y - 30
Строка настроек должна работать на английском и арабском; как обработать переведённый текст и раскладку справа налево?
ui - 31
Выполните GET /users/42 и превратите успешный JSON-ответ в объект пользователя; какие проверки обязательны?
- 32
DELETE /users/42 возвращает 204 No Content; как экран должен обработать ответ и удалить пользователя?
- 33
Стоит ли хранить видео размером 5 МБ или пароль аутентификации в AsyncStorage и для чего оно подходит?
authpasswordsasync - 34
Что managed workflow Expo берёт на себя для junior-разработчика первого приложения с уведомлениями и геолокацией?
android-componentsexpo - 35
Проект добавляет одну нативную библиотеку камеры, которой нет в Expo Go; почему нужен development build?
expo - 36
Пользователь один раз нажимает «Включить уведомления»; когда приложению запросить разрешение и как обработать отказ?
permissionsandroid-components - 37
Экран check-in требует одну фотографию и текущее местоположение; какие базовые шаги идут до использования обоих API устройства?
api - 38
Таймер должен приостанавливаться, когда приложение на 30 секунд уходит в фоновый режим; какой API жизненного цикла React Native вы используете?
reactreact-nativeapi - 39
Development и production сборки вызывают 2 разных базовых URL API; как настроить их без редактирования исходников перед каждой сборкой?
configbuildapi - 40
Почему секретный API-ключ платного сервиса нельзя положить в переменную EXPO_PUBLIC_ даже для одной release-сборки?
secretsapiandroid-components - 41
Как отрендерить 1 000 товаров через FlatList вместо помещения всех строк в один ScrollView?
virtualized-lists - 42
Удалённое изображение имеет размер 1200 на 800 пикселей, но должно поместиться в карточку шириной 300 пунктов; как разумно задать размер и кеширование?
caching - 43
Карточка должна за 300 мс плавно проявиться, изменив opacity с 0 до 1; как это сделать через Reanimated?
cssanimationzero-to-one - 44
Фотография должна двигаться по горизонтали вслед за пальцем и возвращаться после отпускания; что для этого даёт Gesture Handler?
gesturesscaling - 45
Составьте план теста через Jest и React Native Testing Library для LoginForm, где Submit включается только после заполнения 2 полей.
jestrtltest-plans - 46
Что проверит Detox или Maestro в одном release smoke flow, который открывает приложение, входит в аккаунт и показывает Home?
end-to-end-testing - 47
После добавления TypeScript-экрана что делает Metro при запуске React Native-приложения?
reactreact-nativetypescript - 48
Баг появляется только в одной release-сборке; чем она отличается от debug и какие современные инструменты использовать сначала?
- 49
Какой подписанный артефакт обычно отправляют в TestFlight и какие 2 типа Android-артефактов можно собрать?
ios-distributionartifacts - 50
Нужно изменить одну подпись кнопки в команде из 3 человек; опишите безопасный Git workflow от ветки до merge.
git - 51
Android-экран рисуется edge-to-edge, и белые иконки статус-бара пропадают на светлом изображении; как сохранить их читаемость без ещё одной обёртки safe area?
- 52
В форме входа есть поля email и пароля; как сделать так, чтобы кнопка Далее на клавиатуре переводила фокус на пароль, а Готово отправляла форму?
formspasswords - 53
У React Native Modal нет видимого действия закрытия, а аппаратная кнопка Назад на Android его не закрывает; как обработать все пути выхода?
reactreact-native - 54
Небольшой индикатор онлайн поверх аватара исчез после добавления скругления контейнеру изображения; как исправить раскладку?
uicontainers - 55
Двухколоночный экран профиля работает при размере 390 на 844, но обрезается после поворота до 844 на 390; как сделать его адаптивным?
responsiveschema - 56
После отправки появляется баннер ошибки, но пользователь TalkBack ничего не слышит и остаётся на кнопке Отправить; как объявить сбой?
talkback - 57
Когда система переключается в тёмную тему при открытом приложении, 6 подписей становятся тёмными на тёмном фоне; как исправить тему?
themingsystem-design - 58
Русский перевод увеличился с 2 до 4 строк и вытолкнул основную кнопку за пределы экрана высотой 667 пикселей; что вы измените?
- 59
После открытия модального окна с ошибкой фокус VoiceOver ещё 5 секунд остаётся на кнопке за ним; как исправить порядок фокуса?
voiceover - 60
Форма регистрации отправляет пустое имя и email из 5 неверных символов, а затем показывает только общую ошибку 400; как улучшить валидацию?
genericsvalidationforms - 61
GET /products возвращает ETag вместе с 200; как при повторном открытии отправить If-None-Match и обработать 304 через простой локальный кеш?
cachinghttp-caching - 62
Пользователь ищет cat, затем car, но более медленный ответ cat приходит последним и заменяет правильные результаты car; как защититься без AbortController?
- 63
REST-запрос может зависнуть на 45 секунд при слабой связи, но продукт требует показать таймаут через 10 секунд; как вы это реализуете?
resiliencerest - 64
API возвращает по 20 товаров, но два быстрых достижения конца списка дважды добавляют страницу 2; как исправить пагинацию?
pagination - 65
PDF-счёт скачан в локальный URI, но кнопка Открыть на Android ничего не делает; как дать пользователю открыть или поделиться файлом через Expo?
expo - 66
Встреча из ответа 2026-07-16T23:30:00Z показывает неверный календарный день у части пользователей после обрезания первых 10 символов; как это исправить?
- 67
Access token истекает через 30 минут, и следующий API-вызов возвращает 401; какую базовую обработку токена вы реализуете?
tokensapi - 68
Pull-to-refresh запускает второй запрос, пока первый 1,5-секундный refresh ещё идёт, а после ошибки индикатор не останавливается; как это исправить?
- 69
Endpoint обычно возвращает JSON, но proxy присылает HTML-страницу ошибки, и response.json() падает с Unexpected token <; как это обработать?
htmlendpointsproxy - 70
Пользователь загружает фото размером 12 МБ через медленную сеть и видит 0 процентов 20 секунд, а затем 100 процентов; как показать реальный прогресс?
- 71
Маршрут Products может не получить параметр sort, а неверный deep link может передать sort=cheapest-first; как выбрать безопасное значение по умолчанию?
deep-linkingnavigation - 72
После успешного входа Android Back возвращает с Home на экран Login; что нужно изменить в навигации?
navigation - 73
Экрану EditProfile нужна кнопка Save в заголовке native stack, но она отправляет имя из первого рендера; как связать её с текущим состоянием формы?
forms - 74
Экран Receipt открывается из Checkout или напрямую из уведомления, но его кнопка Закрыть вызывает goBack и ничего не делает, когда Receipt является корневым маршрутом; как обработать оба входа?
android-components - 75
Двойное нажатие по карточке товара за 300 миллисекунд открывает два одинаковых экрана Product; как остановить дубликат?
- 76
Badge вкладки Inbox остаётся равным 3 после того, как пользователь отметил все сообщения прочитанными; как синхронизировать его с navigator?
- 77
HomeTabs вложен в root stack, и каждая вкладка показывает два заголовка; как убрать повтор, не потеряв заголовки экранов деталей?
- 78
Приложение отмечает счёт как Отправлен сразу после открытия системного share sheet, даже если пользователь его закрыл; как смоделировать результат?
- 79
Закрытие DocumentPicker показывает Ошибка загрузки, а выбранное изображение размером 40 МБ всё равно уходит в endpoint только для PDF; как обработать оба исхода?
endpoints - 80
Кнопка Support открывает mailto:support@example.com, но на устройстве без настроенного почтового приложения ничего не происходит; какой fallback добавить?
config - 81
В FAQ есть 20 категорий, и заголовок текущей категории должен оставаться видимым при прокрутке вопросов; как построить это через SectionList?
virtualized-lists - 82
Строка настроек содержит иконку, заголовок, статус и chevron, но на нажатие реагирует только текст заголовка; как сделать составную строку одной доступной целью?
- 83
Нажатие строки 7 меняет selectedId, но FlatList не обновляет подсветку, потому что data не изменился; чего не хватает?
virtualized-lists - 84
Вкладка Feed сохраняет позицию списка, но повторное нажатие уже выбранной вкладки должно прокрутить FlatList вверх и сейчас срабатывает дважды после remount; как это реализовать?
virtualized-lists - 85
Изображение профиля использует signed URL, который истекает через 15 минут, и позже ломается, хотя сам аватар не менялся; как восстановить и кешировать его?
caching - 86
Анимация карточки длительностью 300 миллисекунд падает до 40 fps, когда ширина меняется на каждом кадре; как достичь 60 fps?
- 87
Горизонтальный swipe-to-delete внутри вертикального списка перехватывает жест уже после 2 пикселей диагонального движения; как разрешить конфликт?
scaling - 88
Countdown пишет лог каждую секунду даже после ухода с экрана, а возврат создаёт два countdown; какой cleanup нужен?
- 89
Запрос завершился и spinner исчез, но все видимые кнопки остались ненажимаемыми, потому что прозрачный полноэкранный View всё ещё смонтирован; как найти причину?
ui - 90
После добавления Products FlatList внутрь вертикального ScrollView появляется предупреждение о вложенных VirtualizedLists, а прокрутка работает нестабильно; как перестроить экран?
virtualizationvirtualized-lists - 91
Чистая функция formatDuration должна превращать 65 секунд в 01:05; как проверить её без рендера React Native компонента?
reactcomponentsreact-native - 92
Компонент товаров вызывает fetch и должен показать 2 элемента при 200 или ошибку при 500; как замокать эти случаи?
componentsmocking - 93
Какой один end-to-end сценарий докажет, что функция камеры обрабатывает отказ в разрешении, а после выдачи доступа начинает работать?
permissionse2e - 94
В production есть опечатка в подписи кнопки, а следующая задача добавляет новый нативный модуль штрихкодов; какое изменение можно отправить через EAS Update, а какому нужна новая store build?
over-the-air-updates - 95
Metro всё ещё импортирует старое имя модуля через 10 минут после переименования файла, хотя исходники правильные; что вы попробуете?
metro - 96
Экран камеры работает на iOS 18, но сразу закрывается на Android 14; как исследовать платформенный баг?
- 97
Релиз помечен как 1.4.0, но App Store Connect и Google Play отклоняют вторую загрузку с повторно использованными build identifiers; чем отличаются app version, iOS buildNumber и Android versionCode?
- 98
Release показывает старую иконку приложения и белую вспышку на 500 миллисекунд перед splash; что вы проверите?
- 99
Внутренний тестировщик сообщает о пустом экране только на Pixel 6 с Android 15 в build 108; какие данные вы соберёте до изменения кода?
- 100
Android-версия 1.4.0 с исправлением входа только что дошла до 5% rollout; какой один post-release smoke и monitoring сценарий вы выполните?
monitoring