💫

React Native (Expo)での画面遷移いろいろまとめ

2025/02/22に公開

はじめに

最近 Expo に入門しました!
この記事では Expo RouterReact Navigation での画面遷移のいくつかを Gif 画像と共に紹介します!

外部リンク

以下から一覧でも確認できるようにしています!(Tamagui を試したかっただけ 😅)
https://toki-dev.vercel.app/tools/expo-navigation-gallery

この記事で紹介するサンプルコードのリポジトリです!
https://github.com/toki-developer/expo-pagination-example

Stack

import { Stack } from "expo-router";

export default function RootLayout() {
  return (
    <Stack>
      <Stack.Screen name="(tabs)" />
      <Stack.Screen
        name="stack"
        options={{ headerBackButtonDisplayMode: "minimal" }}
      />
    </Stack>
  );
}

https://docs.expo.dev/router/advanced/stack/

Tab

import { Tabs } from "expo-router";

export default function TabLayout() {
  return (
    <Tabs>
      <Tabs.Screen name="index" />
      <Tabs.Screen name="explore" />
    </Tabs>
  );
}

https://docs.expo.dev/router/advanced/tabs/

import { Stack } from "expo-router";

export default function RootLayout() {
  return (
    <Stack>
      <Stack.Screen name="(tabs)" />
      <Stack.Screen name="modal" options={{ presentation: "modal" }} />
    </Stack>
  );
}

https://docs.expo.dev/router/advanced/modals/

Drawer

import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Drawer } from "expo-router/drawer";

export default function DrawerLayout() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <Drawer>
        <Drawer.Screen name="drawer1" />
        <Drawer.Screen name="drawer2" />
      </Drawer>
    </GestureHandlerRootView>
  );
}
メニューのカスタマイズする場合
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { Drawer } from "expo-router/drawer";
import {
  DrawerContentComponentProps,
  DrawerContentScrollView,
  DrawerItem,
  DrawerItemList,
} from "@react-navigation/drawer";
import { router } from "expo-router";
import Feather from "@expo/vector-icons/Feather";
import { Text } from "react-native";

function CustomDrawerContent(props: DrawerContentComponentProps) {
  return (
    <DrawerContentScrollView>
      <Text style={{ textAlign: "center", padding: 16 }}>Hello Drawer</Text>
      <DrawerItemList {...props} />
      <DrawerItem
        label="Stack"
        onPress={() => router.push({ pathname: "/stack" })}
        icon={(props) => <Feather name="smile" size={24} color={props.color} />}
      />
    </DrawerContentScrollView>
  );
}

export default function CustomDrawerLayout() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <Drawer drawerContent={CustomDrawerContent}>
        <Drawer.Screen
          name="custom-drawer1"
          options={{
            title: "Drawer 1",
            drawerIcon: (props) => (
              <Feather name="frown" size={24} color={props.color} />
            ),
          }}
        />
        <Drawer.Screen
          name="custom-drawer2"
          options={{
            drawerIcon: (props) => (
              <Feather name="meh" size={24} color={props.color} />
            ),
          }}
        />
      </Drawer>
    </GestureHandlerRootView>
  );
}

https://docs.expo.dev/router/advanced/drawer/
https://reactnavigation.org/docs/drawer-navigator/

検索

import { router, Stack } from "expo-router";

export default function SearchLayout() {
  return (
    <Stack
      screenOptions={{
        headerSearchBarOptions: {
          placeholder: "検索する",
          inputType: "text",
          onSearchButtonPress(e) {
            router.push({
              pathname: "/search-result",
              params: { q: e.nativeEvent.text },
            });
          },
        },
      }}
    >
      <Stack.Screen name="search" />
      <Stack.Screen name="search-result" />
    </Stack>
  );
}

https://reactnavigation.org/docs/native-stack-navigator/#headersearchbaroptions

Material Top Tab

import {
  createMaterialTopTabNavigator,
  MaterialTopTabNavigationEventMap,
  MaterialTopTabNavigationOptions,
} from "@react-navigation/material-top-tabs";
import { ParamListBase, TabNavigationState } from "@react-navigation/native";
import { withLayoutContext } from "expo-router";
import { SafeAreaView } from "react-native";

const { Navigator } = createMaterialTopTabNavigator();

const MaterialTopTabs = withLayoutContext<
  MaterialTopTabNavigationOptions,
  typeof Navigator,
  TabNavigationState<ParamListBase>,
  MaterialTopTabNavigationEventMap
>(Navigator);

export default function TopTabLayout() {
  return (
    <SafeAreaView style={{ flex: 1 }}>
      <MaterialTopTabs>
        <MaterialTopTabs.Screen name="top-tab1" />
        <MaterialTopTabs.Screen name="top-tab2" />
      </MaterialTopTabs>
    </SafeAreaView>
  );
}

https://reactnavigation.org/docs/material-top-tab-navigator/
https://reactnativepro.dev/posts/expo-router-top-tabs

おわりに

タブやドロワーなどがすごく簡単に実装できていい感じです!
普段は web を開発しているので、モーダル(ページシート)が別ページなのは意外でした!

色変更などスタイルの調整も可能です!
これから、他の option や他のナビゲーションなども試していこうと思います!
(気が向いたらここにも追記します m)

GitHubで編集を提案

Discussion