Урок по треку React Native 7 мин

Компоненты и стили: чем RN отличается от веба

View, Text, Pressable, StyleSheet, Flexbox в RN, платформенные различия и safe area.

React в React Native тот же: компоненты, хуки, пропсы. Отличаются примитивы и стили. Фронтендеры часто спотыкаются как раз об эти отличия, и на собесе их проверяют.

Базовые компоненты

  • View: контейнер, аналог div, но без текста внутри.
  • Text: весь текст обязан быть внутри Text. Строка прямо в View даст ошибку «Text strings must be rendered within a <Text> component».
  • Image: картинки, для удалённых обязательно указать размеры.
  • TextInput: поле ввода, value и onChangeText.
  • Pressable: современный способ обработать нажатие, с состояниями pressed, hovered, onLongPress. TouchableOpacity и другие Touchable* ещё работают, но новые экраны пишут на Pressable.
  • ScrollView: прокрутка, рендерит всех детей сразу. Для длинных данных нужен FlatList.
  • Modal, ActivityIndicator, Switch, KeyboardAvoidingView.

Стили

Стили это объекты JS, свойства в camelCase, числа без единиц (логические пиксели, dp/pt):

const styles = StyleSheet.create({
  card: { padding: 16, borderRadius: 12, backgroundColor: '#fff' },
  title: { fontSize: 18, fontWeight: '600' },
});

<View style={[styles.card, selected && { borderColor: 'tomato', borderWidth: 2 }]} />
  • Массив стилей объединяется слева направо, false и null пропускаются.
  • Каскада и наследования, как в CSS, почти нет. Наследуется только стиль текста от родительского Text к вложенному Text. color у View не повлияет на текст внутри.
  • StyleSheet.create проверяет стили и делает код понятнее. Инлайновые объекты создаются заново при каждом рендере, что мешает memo-компонентам.

Flexbox в RN

Раскладка через Yoga, почти как в вебе, но умолчания другие:

СвойствоВебReact Native
flexDirectionrowcolumn
alignContentnormalflex-start
flexShrink10
positionstaticrelative

flex: 1 в RN означает «занять всё свободное место по главной оси». Ещё одно отличие: display бывает только flex и none (в новых версиях добавлен contents), нет grid и float.

Платформенные различия

import { Platform } from 'react-native';

const styles = StyleSheet.create({
  shadow: Platform.select({
    ios: { shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 8, shadowOffset: { width: 0, height: 2 } },
    android: { elevation: 3 },
  }),
});

Раньше тени на iOS задавались свойствами shadow*, на Android через elevation. Новые версии поддерживают свойство boxShadow в стиле CSS на обеих платформах (с новой архитектурой). Файлы Button.ios.tsx и Button.android.tsx подхватываются сборщиком автоматически по расширению.

Размеры экрана и safe area

useWindowDimensions() возвращает ширину и высоту окна и обновляется при повороте и изменении размера. Dimensions.get даёт снимок на момент вызова и сам не обновляется. Вырезы, «чёлку» и системные панели учитывают через react-native-safe-area-context (SafeAreaView, useSafeAreaInsets). Встроенный SafeAreaView из react-native работает только на iOS и устарел.

Клавиатура перекрывает поля ввода: KeyboardAvoidingView (на iOS обычно behavior="padding") или библиотеки вроде react-native-keyboard-controller.

Доступность

accessibilityLabel, accessibilityRole (или новые aria-* и role), достаточный размер области нажатия (hitSlop), поддержка увеличенного шрифта (не ставить фиксированную высоту текстовым блокам).

Частые ошибки

  • Текст вне Text.
  • Ждать, что flexDirection по умолчанию row.
  • ScrollView с сотнями элементов.
  • Dimensions.get вместо хука при поворотах.
  • Инлайновые объекты стилей в часто перерисовываемых memo-компонентах.

Что спросят на собесе

  • Чем стили RN отличаются от CSS.
  • Умолчания Flexbox в RN.
  • Как писать платформенно-зависимый код.
  • Pressable против TouchableOpacity.
  • Как учесть вырезы экрана и клавиатуру.

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.