логотип PurpleSchool
логотип PurpleSchool

Создание и использование tabs в React Native

Автор

Олег Марков

Введение

Вкладки (tabs) — привычный элемент интерфейса, который помогает организовать навигацию между различными разделами приложения. Реализация вкладок позволяет структурировать контент, упростить доступ к ключевым экранам и повысить удобство использования вашего мобильного приложения. В React Native создание tabs может быть реализовано разными способами — от использования стандартных компонентов до интеграции сторонних библиотек для полноценной таб-навигации, поддерживающей анимацию и жесты.

В этой статье покажу вам, как создавать и настраивать вкладки в React Native, рассмотрим лучшие библиотеки для реализации этого функционала, а также разберем примеры кода с комментариями. Поговорим о плюсах и минусах разных подходов, затронем вопросы кастомизации внешнего вида вкладок и рассмотрим, как tabs интегрируются с навигацией в мобильных приложениях на React Native.

Краткий обзор способов создания tabs в React Native

Прежде чем погружаться в детали, давайте опишу основные стратегии:

  • Стандартные компоненты и ручная организация вкладок — когда вы сами отображаете нужный компонент в зависимости от выбранной вкладки.
  • Сторонние библиотеки — такие как react-navigation (и его подбиблиотека @react-navigation/bottom-tabs), а также популярная библиотека react-native-tab-view.
  • Кастомные реализации — когда вы пишете полностью свой компонент вкладок, если нужно специальное поведение или дизайн.

Чаще всего используются готовые библиотеки, чтобы получить красивый и удобный функционал с минимальными усилиями.

Давайте начнем с простейшей ручной реализации.

Вкладки (tabs) - это распространенный элемент пользовательского интерфейса, который позволяет пользователям легко переключаться между различными разделами приложения. В React Native существует несколько способов создания вкладок, и выбор правильного подхода зависит от требований к дизайну и функциональности. Для создания удобных и интуитивно понятных интерфейсов, важно понимать особенности различных библиотек и уметь их настраивать. Если вы хотите детальнее погрузиться в мир React Native и научиться создавать сложные интерфейсы с использованием вкладок — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Пример собственной реализации tabs на React Native

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

import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';

const MyTabs = () => {
  const [activeTab, setActiveTab] = useState(0); // Храним индекс активной вкладки

  return (
    <View style={styles.container}>
      {/* Здесь размещаем кнопки вкладок */}
      <View style={styles.tabBar}>
        <TouchableOpacity style={[styles.tabButton, activeTab === 0 && styles.activeTab]} onPress={() => setActiveTab(0)}>
          <Text style={activeTab === 0 ? styles.activeText : styles.tabText}>Вкладка 1</Text>
        </TouchableOpacity>
        <TouchableOpacity style={[styles.tabButton, activeTab === 1 && styles.activeTab]} onPress={() => setActiveTab(1)}>
          <Text style={activeTab === 1 ? styles.activeText : styles.tabText}>Вкладка 2</Text>
        </TouchableOpacity>
      </View>
      {/* Контент выбранной вкладки */}
      <View style={styles.tabContent}>
        {activeTab === 0 ? (
          <Text>Контент первой вкладки</Text>
        ) : (
          <Text>Контент второй вкладки</Text>
        )}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, marginTop: 40 },
  tabBar: { flexDirection: 'row', justifyContent: 'center', marginBottom: 10 },
  tabButton: { padding: 10, backgroundColor: '#eee', margin: 2, borderRadius: 6 },
  activeTab: { backgroundColor: '#2196f3' }, // Активная вкладка выделена цветом
  tabText: { color: '#333' },
  activeText: { color: '#fff' },
  tabContent: { alignItems: 'center', justifyContent: 'center', flex: 1 }
});

export default MyTabs;

Давайте разберёмся:

  • С помощью состояния (activeTab) определяем, какая вкладка активна.
  • Используем TouchableOpacity для имитации кнопок вкладок.
  • Стилизуем активную вкладку отдельно.
  • Показываем нужный контент на основе выбранного индекса.

Такой подход хорош для очень простых случаев, но у него есть ограничения: отсутствуют анимации, свайпы, плохая масштабируемость и кастомизация.

Теперь давайте рассмотрим популярные библиотеки, которые дают гораздо больше возможностей.

Использование react-navigation с Bottom Tabs

Самое распространённое решение — навигация с помощью библиотеки react-navigation. Она давно стала стандартом для мобильных приложений на React Native и включает удобные API для создания вкладок.

Установка зависимостей

Вам потребуется:

  • @react-navigation/native
  • @react-navigation/bottom-tabs
  • Плюс несколько зависимостей, необходимых для работы самой навигации.

Давайте начнем:

npm install @react-navigation/native @react-navigation/bottom-tabs
npm install react-native-screens react-native-safe-area-context

Для Expo этого обычно достаточно. Для bare React Native внимательно следите за документацией и настройте react-native-reanimated, если необходимо.

Создание вкладок с помощью createBottomTabNavigator

Смотрите, я покажу вам пример кода для реализации нижней панели вкладок (Bottom Tabs):

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeScreen from './screens/HomeScreen'; // Ваши компоненты-экраны
import SettingsScreen from './screens/SettingsScreen';

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Главная" component={HomeScreen} />
        <Tab.Screen name="Настройки" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Здесь:

  • Tab.Navigator описывает панель вкладок.
  • Tab.Screen регистрирует каждый экран, который будет на своей вкладке.

Кастомизация внешнего вида вкладок

Вы легко можете настроить иконки, цвета, шрифты вкладок:

<Tab.Navigator
  screenOptions={({ route }) => ({
    tabBarIcon: ({ focused, color, size }) => {
      // Покажу пример с react-native-vector-icons
      let iconName;
      if (route.name === 'Главная') {
        iconName = focused ? 'home' : 'home-outline';
      } else if (route.name === 'Настройки') {
        iconName = focused ? 'settings' : 'settings-outline';
      }
      // Возвращаем компонент иконки (зависит от выбранной библиотеки иконок)
      return <Ionicons name={iconName} size={size} color={color} />;
    },
    tabBarActiveTintColor: '#2196f3',
    tabBarInactiveTintColor: 'gray',
    tabBarStyle: { backgroundColor: '#f5f5f5', paddingBottom: 4 },
    // Дополнительные параметры
  })}
>
  {/* ... экраны */}
</Tab.Navigator>

Комментарии к этому примеру:

  • В функции tabBarIcon можно подставлять любые компоненты, иконки и менять стиль иконок в зависимости от фокуса.
  • tabBarActiveTintColor и tabBarInactiveTintColor управляют цветами текста/иконок.
  • Не забывайте импортировать и использовать выбранную библиотеку иконок, например, Ionicons.

Верхние вкладки (Material Top Tabs)

Вам может понадобиться верхняя панель вкладок. Для этого в экосистеме react-navigation существует пакет @react-navigation/material-top-tabs, основанный на реализации TabView от React Native Community.

Установка

npm install @react-navigation/material-top-tabs react-native-tab-view

Пример

import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
const TopTab = createMaterialTopTabNavigator();

export default function TopTabs() {
  return (
    <NavigationContainer>
      <TopTab.Navigator>
        <TopTab.Screen name="Feed" component={FeedScreen} />
        <TopTab.Screen name="Messages" component={MessagesScreen} />
      </TopTab.Navigator>
    </NavigationContainer>
  );
}

Дополнительные опции для стилизации верхней панели:

  • tabBarIndicatorStyle — кастомизация линии под активной вкладкой
  • tabBarLabelStyle, tabBarStyle и другие — для стиля текста вкладок и общей панели

Вложенные вкладки и интеграция с StackNavigator

Часто вкладки — только часть вашей архитектуры. Например, одна вкладка может быть Stack Navigator'ом.

import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Главная" component={HomeStack} />
        <Tab.Screen name="Настройки" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Обратите внимание, как удобно можно комбинировать разные типы навигации, если вы используете библиотеки react-navigation.

Использование react-native-tab-view для гибких интерфейсов

Если вы хотите реализовать своеобразные вкладки внутри одного экрана (например, свайп между вкладками без изменения навигационного маршрута), вам пригодится библиотека react-native-tab-view.

Установка

npm install react-native-tab-view

Базовый пример использования

import * as React from 'react';
import { View, Text, StyleSheet, useWindowDimensions } from 'react-native';
import { TabView, SceneMap, TabBar } from 'react-native-tab-view';

const FirstRoute = () => (
  <View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
    <Text>Первая вкладка</Text>
  </View>
);

const SecondRoute = () => (
  <View style={[styles.scene, { backgroundColor: '#673ab7' }]}>
    <Text>Вторая вкладка</Text>
  </View>
);

export default function TabViewExample() {
  const layout = useWindowDimensions();

  const [index, setIndex] = React.useState(0);
  const [routes] = React.useState([
    { key: 'first', title: 'Вкладка 1' },
    { key: 'second', title: 'Вкладка 2' },
  ]);

  return (
    <TabView
      navigationState={{ index, routes }}
      renderScene={SceneMap({
        first: FirstRoute,
        second: SecondRoute,
      })}
      onIndexChange={setIndex}
      initialLayout={{ width: layout.width }}
      renderTabBar={props => (
        <TabBar
          {...props}
          indicatorStyle={{ backgroundColor: 'white' }}
          style={{ backgroundColor: '#2196f3' }}
          labelStyle={{ color: '#fff', fontWeight: 'bold' }}
        />
      )}
    />
  );
}

const styles = StyleSheet.create({
  scene: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Вот как это работает:

  • Вы задаёте список маршрутов (routes) и способ отрисовки каждой вкладки (renderScene).
  • С помощью TabBar можно полностью кастомизировать вид панели вкладок.
  • Свайпы между вкладками реализованы из коробки — удобно для UI, похожего на Instagram или Tinder.

Часто компонент react-native-tab-view применяют в интерфейсах с «Tab внутри экрана», а не для глобальной навигации между экранами.

Гибкая настройка и кастомизация

Покажу, как, например, изменить цвета индикатора и шрифт подписи:

renderTabBar={props => (
  <TabBar
    {...props}
    indicatorStyle={{ backgroundColor: '#ff5722', height: 4 }}
    style={{ backgroundColor: '#263238' }}
    labelStyle={{ color: '#fff', fontSize: 16 }}
    tabStyle={{ width: 120 }}
    scrollEnabled // позволяет вкладкам прокручиваться, если их много
  />
)}

Вы можете заменить панель вкладок на полностью свою, если передадите собственную функцию в пропс renderTabBar. Это позволяет даже добавить нестандартные элементы вроде кнопки "+" рядом с вкладками.

Советы по проектированию и кастомизации tabs

Когда использовать Bottom Tabs, а когда TabView?

  • Bottom tabs (react-navigation/bottom-tabs) — идеально для основной навигации между крупными разделами приложения (пример — Instagram: Домой, Поиск, Добавить, Уведомления, Профиль).
  • Top tabs или TabView — удобно для организации контента внутри конкретного раздела (например, подкатегории в разделе магазина: Новинки, Лидер продаж, Скидки).

Советы по комбинации навигаций

React Navigation позволяет комбинировать Stack, Tabs и Drawer навигации. Не бойтесь вкладывать их друг в друга для удобной архитектуры. Главное — подумайте, какая навигация должна быть основной (обычно это Tabs или Drawer) и разбейте логику приложения на "разделы".

Как сделать кастомный TabBar

Иногда стандартного вида вкладок может быть недостаточно. В react-navigation вы можете использовать свой компонент панели вкладок:

<Tab.Navigator tabBar={props => <MyCustomTabBar {...props} />} />

Внутри собственной функции вы получите информацию о текущих вкладках, активной вкладке и сможете реализовать абсолютно уникальный дизайн.

Проблемы и типичные ошибки при работе с tabs

Проблема с анимацией переходов

Обычно анимация работает “из коробки”, но если возникают подвисания или мерцания, попробуйте:

  • Использовать внешний компонент react-native-reanimated
  • Проверить, что компоненты внутри вкладок не блокируют поток выполнения

Проблема с сохранением состояния вкладок

Если пользователь переключает вкладку, а состояние сбрасывается — используйте опцию unmountOnBlur: false (для react-navigation). Это поможет сохранить стейт компонента, когда он неактивен.

<Tab.Screen
  name="User"
  component={UserScreen}
  options={{ unmountOnBlur: false }}
/>

Не отображаются иконки

Часто забывают подключить библиотеку иконок вроде react-native-vector-icons. Убедитесь, что вы установили пакет и импортировали конкретный набор иконок.

Не работает свайп между вкладками

Для верхних вкладок и реализации на react-native-tab-view свайпы есть всегда. В bottom-tabs этот функционал специально отсутствует — так устроен Material Design.

Заключение

Tabs — мощный инструмент для организации навигации и разделения контента в приложениях. В React Native у вас есть как простые нативные способы реализации, так и гибкие, более сложные через сторонние библиотеки вроде react-navigation и react-native-tab-view. Выбор подхода зависит от архитектуры приложения и требований к пользовательскому интерфейсу.

Используйте ручную реализацию только для очень простых или уникальных случаев. Во всех остальных случаях стоит обращаться к готовым стабильным решениям, которые покрывают большинство задач.

Тестируйте навигацию на разных устройствах, чтобы убедиться, что интерфейс tabs работает плавно и дружелюбно для ваших пользователей. Пишите код так, чтобы вы легко могли расширять и модифицировать tabs в будущем.

Создание вкладок - это только один из аспектов разработки качественного React Native приложения. Для создания полноценного приложения необходимо освоить множество других технологий и подходов, включая работу с UI, данными и нативными функциями. Курс React Native и Expo Router поможет вам в этом. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.

Частозадаваемые технические вопросы по теме статьи и ответы на них

1. Как сделать скрытие панели вкладок на одном из экранов?

Добавьте в опции экрана параметр:

<Tab.Screen
  name="HideMe"
  component={MyComponent}
  options={{ tabBarStyle: { display: 'none' } }}
/>

Это скроет вкладки, когда активирован экран.

2. Как добавить бейджи или счетчики на вкладки?

Передайте параметр tabBarBadge:

<Tab.Screen
  name="Notifications"
  component={NotificationsScreen}
  options={{ tabBarBadge: 3 }} // Показывает бейдж с числом 3
/>

Для кастомных бейджей настройте свой tabBarIcon.

3. Как реагировать на нажатие вкладки (например, прокручивать до верха списка)?

Используйте собственный обработчик через слушатель события в навигаторе:

useEffect(() => {
  const unsubscribe = navigation.addListener('tabPress', e => {
    // Например, листаем FlatList вверх
    flatListRef.current.scrollToOffset({ offset: 0 });
  });
  return unsubscribe;
}, [navigation]);

4. Почему вложенные вкладки не обновляются при переключении родительского Stack Navigator?

Проверьте, не используете ли вы unmountOnBlur. Если да, установите параметр в false или сохраняйте состояние самостоятельно через глобальный стейт.

5. Как реализовать динамический список вкладок (например, добавлять/убирать вкладки во время работы приложения)?

Вместо жестко заданного массива экраны вкладок храните список экранов во внешнем массиве (например, в состоянии Redux или Context) и рендерьте экраны через .map() или динамический список. Например, в TabView можно обновлять routes динамически.

Стрелочка влево5 популярных библиотек UI компонентов React NativeРуководство по стилизации компонентов в React NativeСтрелочка вправо

Постройте личный план изучения React-native до уровня Middle — бесплатно!

React-native — часть карты развития Mobile

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по React-native

Работа со ScrollView в React NativeРабота с видео в React NativeКак реализовать аудиоплеер на React NativeНастройка и использование input и textinput в React NativeИнтеграция видео плеера в приложение на React NativeИспользование выпадающих списков в React NativeСоздание и настройка native module на React NativeКак создать модальные окна в React NativeРабота с изображениями в React NativeОтображение списков данных в React NativeГайд по файловой системе в React NativeИнтеграция камеры в приложение на React NativeСоздание интерактивных кнопок в React Native
Как использовать векторные иконки в React Native5 популярных библиотек UI компонентов React NativeСоздание и использование tabs в React NativeРуководство по стилизации компонентов в React NativeОптимизация переходов между экранами в React NativeАдаптация safe area context на React NativeОбзор библиотек для навигации в React NativeСоздание сложных анимаций (reanimated) на React NativeИспользование библиотеки стилей Paper в React NativeРуководство по navigation в React NativeОптимизация отображения списков в React NativeКак реализовать linking на React NativeГайд по UI-китам для React NativeГде искать elements для приложения на React NativeРабота с цветами в React Native
Открыть базу знаний

Лучшие курсы по теме

изображение курса

React Native и Expo Router

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Основы JavaScript

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий