React Native ナビゲーション

概要: このチュートリアルでは、React Native アプリケーションで異なる画面間をナビゲートするために、React Navigation ライブラリを使用する方法を学習します。

React Navigation の紹介

React Native アプリケーション内で異なる画面間の管理とナビゲーションを行うには、React Navigation ライブラリを使用できます。

React Navigation ライブラリには、次の主な機能があります。

  • スタックナビゲーションは、画面をスタックのように管理し、前後の画面をナビゲートできます。
  • ボトムタブナビゲーションは、画面の下部にバーを表示します。バーには、アイコンとラベルが付いた項目が含まれています。各タブバー項目をタップすると、タブナビゲーションによって画面間を移動します。
  • ドロワーナビゲーションは、メニュー項目を表示するためにスワイプして切り替えることができるサイドバー(またはドロワーメニュー)を表示します。

React Native アプリケーションでは、さまざまなナビゲーションを組み合わせて、柔軟なナビゲーションオプションを作成できます。このチュートリアルでは、スタックナビゲーションの作成に焦点を当てます。

React Navigation を使用した React Native アプリケーションの作成

このセクションでは、アプリでのスタックナビゲーションのセットアップと使用方法について説明します。

要件

始める前に、次のものがあることを確認してください。

  • react-native >= 0.63.0
  • expo >= 41 (Expo Go を使用する場合)

新規プロジェクトの設定

まず、ターミナルを開き、次のコマンドを実行して新しい React Native アプリを作成します。

npx create-expo-app nav --template blank

このコマンドは、nav ディレクトリを作成し、React Native アプリを初期化します。完了するまでに時間がかかります。

次に、プロジェクトディレクトリ nav に移動します。

cd nav

次に、次のコマンドを実行して React Navigation ライブラリをインストールします。

npm install @react-navigation/native @react-navigation/native-stackCode language: CSS (css)

基本的な React Navigation の概念

ナビゲーター

ナビゲーターは、ナビゲーションの状態と画面を管理できるコンポーネントです。React Navigation には、次のナビゲーターが含まれています。

  • StackNavigator – スタックナビゲーションの管理用。
  • TabNavigator – ボトムタブナビゲーションの管理用。
  • DrawerNavigator – ドロワーの作成用。

画面

画面は、ナビゲーター内の画面を表す React Native コンポーネントです。ナビゲーターは、各画面をルートに関連付けます。

ルート

ルートは、画面のパスとパラメーターを定義するオブジェクトです。

Navigation プロップ

navigation プロップは、スタックナビゲーション内のすべての画面コンポーネントで使用できます。これにより、navigategoBackpushpop などのナビゲーションメソッドにアクセスできます。

パラメーター

パラメーターは、ある画面から別の画面に渡すパラメーターです。

たとえば、ホーム画面からプロフィール画面に、id と name を含むオブジェクトを渡すことができます。プロフィール画面では、パラメーターを読み取ってさらに処理できます。

ネイティブスタックナビゲーターの作成

ステップ1. 画面を格納するための、プロジェクトディレクトリ内に screens という新しいディレクトリを作成します。各画面は React Native コンポーネントです。

ステップ2. screens ディレクトリに Home 画面を作成します。

import { SafeAreaView, StyleSheet, Text, View } from 'react-native';

const Home = () => {
    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.screen}>
                <Text>Home Screen</Text>
            </View>
        </SafeAreaView>
    );
}

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

export default Home;Code language: JavaScript (javascript)

ステップ3. screens ディレクトリに Profile 画面を作成します。

import { SafeAreaView, StyleSheet, Text, View } from 'react-native';

const Profile = () => {
    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.screen}>
                <Text>Profile Screen</Text>
            </View>
        </SafeAreaView>
    );
}

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

export default Profile;Code language: JavaScript (javascript)

ステップ4. screens ディレクトリに index.js を作成し、HomeProfile 画面をインポートしてすぐにエクスポートします。

import Home from './Home.jsx';
import Profile from './Profile.jsx';

export { Home, Profile }Code language: JavaScript (javascript)

これにより、単一のインポートを使用して screens ディレクトリからすべての画面をインポートできます。

import { Home, Profile} from './screens/index';Code language: JavaScript (javascript)

そして、このように個別に画面をインポートする必要はありません。

import Home from './screens/Home';
import Profile from './screens/Profile';Code language: JavaScript (javascript)

ステップ5. HomeProfile 画面を App.js ファイルにインポートし、Home 画面をメインコンポーネントとして配置します。

import { Home, Profile } from './screens/index';

export default function App() {
  return (
    <Home />
  );
}Code language: JavaScript (javascript)

ステップ6. ターミナルを開いてアプリを実行します。

npm start

ステップ7. ネイティブスタックナビゲーターを作成するために App.js を変更します。

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Home, Profile } from './screens/index';

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={Home} />
        <Stack.Screen name="Profile" component={Profile} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}Code language: JavaScript (javascript)

仕組み

まず、React Navigation ライブラリから NavigationContainercreateNativeStackNavigator をインポートします。

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';Code language: JavaScript (javascript)

次に、createNativeStackNavigator 関数を呼び出してスタックナビゲーターを作成します。

const Stack = createNativeStackNavigator();Code language: JavaScript (javascript)

変数名は Stack である必要はありません。

createNativeStackNavigator() 関数は、オブジェクト(Stack)を返します。このオブジェクトには、両方ともナビゲーターを構成するための React コンポーネントである2つのプロパティがあります。

  • 画面
  • ナビゲーター

次に、NavigationContainer コンポーネントをアプリのルートコンポーネントとして使用します。

<NavigationContainer>
   <Stack.Navigator initialRouteName="Home">
     <Stack.Screen name="Home" component={Home} />
     <Stack.Screen name="Profile" component={Profile} />
    </Stack.Navigator>
</NavigationContainer>
Code language: HTML, XML (xml)

Screen コンポーネントには、namecomponent プロップが含まれています。

  • name プロップは、ナビゲーションに使用されるルート名を指定します。
  • component プロップは、レンダリングする React Native コンポーネントまたは画面を定義します。

スタックナビゲーターには、HomeProfile の2つのルートがあります。最初のルートは、Home 画面を表示する Home ルートです。

initialRouteNameProfile に変更すると、Home 画面ではなく Profile 画面が表示されます。

画面間の移動

ステップ1. Profile 画面に移動するためのボタンを含めるように Home 画面を変更します。

import { SafeAreaView, StyleSheet, Text, View, Pressable } from 'react-native';
import React from 'react';

const Home = ({ navigation }) => {
    const handlePress = () => {
        navigation.navigate('Profile');
    }
    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.screen}>
                <Text>Home Screen</Text>
                <Pressable onPress={handlePress} style={styles.button}>
                    <Text style={styles.buttonText}>Go to the Profile screen</Text>
                </Pressable>
            </View>
        </SafeAreaView>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    screen: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    button: {
        backgroundColor: '#FFD966',
        paddingHorizontal: 20,
        paddingVertical: 10,
        borderRadius: 99,
        alignItems: 'center',
        marginVertical: 10,

    },
    buttonText: {
        color: '#4B4942',
        fontSize: 16,
    },
});

export default Home;Code language: JavaScript (javascript)

ボタンを押すと、Profile 画面に移動します。ヘッダーの戻るボタンをタップすると、Home 画面に戻ります。

仕組み

まず、Home コンポーネントに navigation プロップを含めます。ナビゲーションスタックに含まれるすべての画面には、自動的に navigation プロップが含まれます。

const Home = ({ navigation }) => {Code language: JavaScript (javascript)

次に、Profile ルート名を使用して navigation オブジェクトの navigate() メソッドを呼び出すことで、handlePress コールバックで Profile 画面に移動します。

const handlePress = () => {
   navigation.navigate('Profile');
}Code language: JavaScript (javascript)

Profile 画面からプログラムで Home 画面に戻る場合は、navigation オブジェクトの goBack() メソッドを使用できます。

ステップ2. 押すと Home 画面に戻るボタンを含めるように Profile 画面を変更します。

import { SafeAreaView, StyleSheet, Text, View, Pressable } from 'react-native';

const Profile = ({ navigation }) => {
    const handlePress = () => {
        navigation.goBack();
    }

    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.screen}>
                <Text>Profile Screen</Text>

                <Pressable onPress={handlePress} style={styles.button}>
                    <Text style={styles.buttonText}>Go back to the Home screen</Text>
                </Pressable>
            </View>
        </SafeAreaView>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    screen: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    button: {
        backgroundColor: '#FFD966',
        paddingHorizontal: 20,
        paddingVertical: 10,
        borderRadius: 99,
        alignItems: 'center',
        marginVertical: 10,

    },
    buttonText: {
        color: '#4B4942',
        fontSize: 16,
    },
});

export default Profile;Code language: JavaScript (javascript)

画面間でのデータの受け渡し

画面間でデータを渡すには、次の手順に従います。

まず、navigation.navigate() メソッドの2番目の引数としてオブジェクトを渡します。

navigation.navigate(routeName, {
   id: 1, 
   name: 'John Doe'
});Code language: CSS (css)

次に、route.params オブジェクトを使用して別の画面でデータを読み取ります。

const data = route.params;Code language: JavaScript (javascript)

navigation プロップと同様に、route はコンポーネントのプロップです(例:)。

const Profile = ({ navigation, route }) => {
}Code language: JavaScript (javascript)

また、デストラクチャリングを使用して route.params オブジェクトからデータを取り出すこともできます。

const {id, message} = route.params;Code language: JavaScript (javascript)

次の例は、Home 画面から Profile 画面にデータを渡す方法を示しています。

ステップ1. navigation.navigate() メソッドの2番目の引数としてオブジェクトを渡すように handlePress 関数を変更します。

const handlePress = () => {
    navigation.navigate('Profile', {
          id: 1,
          name: 'John Doe',
    });
}Code language: JavaScript (javascript)

ステップ2. Home 画面から渡されたデータを読み取るように Profile 画面を変更します。

import { SafeAreaView, StyleSheet, Text, View, Pressable } from 'react-native';

const Profile = ({ navigation, route }) => {
    const { id, name } = route.params;
    const handlePress = () => {
        navigation.goBack();
    }

    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.screen}>
                <Text>id: {id}</Text>
                <Text>name: {name}</Text>
                <Pressable onPress={handlePress} style={styles.button}>
                    <Text style={styles.buttonText}>Go back to the Home screen</Text>
                </Pressable>
            </View>
        </SafeAreaView>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    screen: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    button: {
        backgroundColor: '#FFD966',
        paddingHorizontal: 20,
        paddingVertical: 10,
        borderRadius: 99,
        alignItems: 'center',
        marginVertical: 10,

    },
    buttonText: {
        color: '#4B4942',
        fontSize: 16,
    },
});

export default Profile;Code language: JavaScript (javascript)

仕組み

まず、route.params オブジェクトから idname をデストラクチャリングします。

const { id, name } = route.params;Code language: JavaScript (javascript)

次に、画面に id と name を表示します。

<Text>id: {id}</Text>
<Text>name: {name}</Text>Code language: JavaScript (javascript)

画面ヘッダーのカスタマイズ

ヘッダータイトルの変更

Screen コンポーネントには、画面ヘッダーの構成に使用されるオブジェクトまたはオブジェクトを返す関数を許可する options プロップがあります。

たとえば、次のように Home 画面の Home タイトルを Welcome に変更できます。

<Stack.Screen
  name="Home"
  component={Home}
  options={{ title: 'Welcome' }}
/>Code language: JavaScript (javascript)

この例では、Home 画面の options プロップを title'Welcome' のオブジェクトに設定しています。Home 画面はAndroidでは次の画像のようになります。

React Native Navigation - Changing header title

ヘッダータイトルに params を使用するには、options プロップに関数を渡し、route を介して params にアクセスする必要があります。

たとえば、次の例は、name パラメーターを Profile 画面のヘッダータイトルとして使用する方法を示しています。

<Stack.Screen
  name="Profile"
  component={Profile}
  options={({ route }) => ({ title: route.params.name })}
/>Code language: JavaScript (javascript)

この例では、アロー関数options プロップに渡しています。関数は route プロップにアクセスし、ヘッダーのタイトルを name パラメーターに設定します。

React Native Navigation - Changing header title to params

さらに、navigation オブジェクトの setOptions メソッドを呼び出すことによって、アクティブな画面の options を更新することもできます。

navigation.setOptions({title: 'John Doe Profile'})Code language: JavaScript (javascript)

ヘッダースタイルのカスタマイズ

動的にタイトルを変更することに加えて、次のプロパティを使用して画面ヘッダーのスタイルをカスタマイズできます。

  • headerStyle プロパティは、ヘッダーをラップする View に適用されるスタイルを定義します。たとえば、ヘッダーの背景色を設定できます。
  • headerTintColor プロパティは、戻るボタンとタイトルの色を定義します。
  • headerTitleStyle プロパティは、fontFamilyfontWeight、およびその他のTextスタイルなどのタイトルのスタイルを定義します。

次の例は、Home 画面のヘッダースタイルを変更します。

<Stack.Screen
  name="Home"
  component={Home}
  options={{
    title: 'Welcome',
    headerStyle: {
      backgroundColor: '#FFD966',
    },
    headerTintColor: '#4B4942',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
  }}
/>Code language: JavaScript (javascript)
React Native Navigation - Changing header style

すべての画面(Home 画面と Profile 画面を含む)で同じヘッダースタイルを共有するには、screenOptions プロップの下でネイティブスタックナビゲーターに構成を移動できます。

<Stack.Navigator
  initialRouteName="Home"
  screenOptions={{
    headerStyle: {
      backgroundColor: '#FFD966',
    },
    headerTintColor: '#4B4942',
    headerTitleStyle: {
      fontWeight: 'bold',
    }
  }}>
{/* ... */}
</Stack.Navigator>    Code language: JavaScript (javascript)

これで、Home 画面と Profile 画面を含むすべての画面が同じヘッダースタイルを共有します。

ヘッダーをカスタムコンポーネントに置き換える

React Navigation を使用すると、ヘッダータイトルをカスタムコンポーネントに置き換えることができます。たとえば、

ステップ1. React コンポーネントを格納するための components という新しいディレクトリを作成します。

ステップ2. components ディレクトリ内に ProfileHeaderTitle という新しいコンポーネントを作成します。

import { StyleSheet, Text, View } from 'react-native';
import Feather from 'react-native-vector-icons/Feather';

const ProfileHeaderTitle = ({ name }) => {
    return (
        <View style={styles.container}>
            <Feather name="user" size={24} color="#4B4942" />
            <Text style={styles.title}>{name}</Text>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'space-between',
        gap: 10
    },
    title: {
        fontSize: 16,
        fontWeight: 'bold',
        color: '#4B4942'
    },

});

export default ProfileHeaderTitle;Code language: JavaScript (javascript)

ステップ3. Profile 画面のヘッダータイトルに ProfileHeaderTitle コンポーネントを使用するように App.js を変更します。

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Home, Profile } from './screens/index';
import ProfileHeaderTitle from './components/ProfileHeaderTitle';

const Stack = createNativeStackNavigator();

export default function App() {

  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerStyle: {
            backgroundColor: '#FFD966',
          },
          headerTintColor: '#4B4942',
          headerTitleStyle: {
            fontWeight: 'bold',
          }
        }}>
        <Stack.Screen
          name="Home"
          component={Home}
          options={{
            title: 'Welcome'
          }}
        />
        <Stack.Screen
          name="Profile"
          component={Profile}
          options={({ route }) => ({
            headerTitle: () => <ProfileHeaderTitle name={route.params.name} />,
          })}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}Code language: JavaScript (javascript)

まとめ

  • React Navigation ライブラリを使用して、画面間の管理とナビゲーションを行います。
このチュートリアルは役に立ちましたか?