見出し画像

React Native の Context によるコンポーネントツリー全体でのデータ共有を試す

「React Native」の「Context」によるコンポーネントツリー全体でのデータ共有を試したのでまとめました。


前回

1. Context

React」の「Context」は、コンポーネントツリー全体でのデータ共有を行うための仕組みです。

2. Context の使用

「Context」を使用する手順は、次のとおりです。

(1) React Nativeプロジェクトの作成。

npx react-native init my_app
cd my_app

(2) パッケージのインストール。

npm install @react-navigation/native @react-navigation/stack
npm install react-native-screens react-native-safe-area-context
npm install react-native-gesture-handler

2-2. iOSのセットアップ

(1) podのインストール。

cd ios
pod install
cd ..

(2) workspaceを開き、署名し、iPhoneにインストールできることを確認。

2-3. Context と Providerの準備

(1) 「Context」と「Provider」の準備。
AppContext.tsx」を作成して、次のように編集します。

・AppContext.tsx

import React, { createContext, useState, useEffect, ReactNode } from 'react';

// Contextの準備
interface AppContextType {
  login: boolean;
  setLogin: (login: boolean) => void;
}
export const AppContext = createContext<AppContextType | undefined>(undefined);

// Providerの準備
interface AppProviderProps {
  children: ReactNode;
}
export const AppProvider: React.FC<AppProviderProps> = ({ children }) => {
  // 状態
  const [login, setLogin] = useState<boolean>(false);

  // UI
  return (
    <AppContext.Provider value={{ login, setLogin }}>
      {children}
    </AppContext.Provider>
  );
};

「Context」の構成要素は、次の3つです。

・Context : データ共有の基盤。createContext()で作成
・Provider : Contextの値を提供するコンポーネント
・Consumer: Contextの値を使用するコンポーネント

「AppContext.tsx」では、「Context」と「Provider」を定義しています。

2-4. Context のデータへのアクセス

Stack構造の画面を作成し、各画面で「Context」にアクセスします。
今回の「画面構成」とコードの構成は、次のとおりです。

・App.tsx : アプリルート
・Main
: Stack[2]
 ・index.tsx
: Mainの画面構成
 ・home.tsx
: Home画面
 ・detail.tsx
: Detail画面

(1) コードの編集。
「App.tsx」を編集し、「Main」フォルダを作成し、「index.tsx」「home.tsx」「detail.tsx」を追加します。

・App.tsx

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { AppProvider } from './AppContext';
import Main from './Main';

// アプリ
function App() {
  return (
    <NavigationContainer>
      <AppProvider>
          <Main/>
      </AppProvider>
    </NavigationContainer>
  );
}

export default App;

今回は、<Main>を「Provider」で囲んでいます。これによって、<Main>下のコンポーネントで「Context」にアクセスできるようになります。

・Main/index.tsx

import React from 'react';
import { createStackNavigator, CardStyleInterpolators } from '@react-navigation/stack';
import HomeScreen from './home';
import DetailScreen from './detail';

// Stackの準備
const Stack = createStackNavigator();

// Mainの画面構成
function Main() {
  return (
    <>
      <Stack.Navigator 
        initialRouteName="Home"
        screenOptions={{
          cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
        }}>
        <Stack.Screen name="Home画面" component={HomeScreen} />
        <Stack.Screen name="Detail画面" component={DetailScreen} />
      </Stack.Navigator>
    </>
  );
}

export default Main;

・Main/home.tsx

import React, { useContext } from 'react';
import { View, Text, Button } from 'react-native';
import { AppContext } from '../AppContext';

// Home画面コンポーネント
// @ts-ignore
function HomeScreen({ navigation }) {
  // コンテキストの取得
  const appContext = useContext(AppContext);
  if (!appContext) return null;
  const { login, setLogin } = appContext;

  // UI
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home画面</Text>
      <Button
        title='Detail画面に遷移'
        onPress={() => navigation.navigate('Detail画面')}
      />
      <Text/>
      <Text>
        {login ? 'Login' : 'Logout'}
      </Text>
      <Button
        title={login ? 'Logout' : 'Login'}
        onPress={() => setLogin(!login)} 
      />      
    </View>
  );
}

export default HomeScreen;

useContext() で「Context」を取得して各種操作を行います。

・Main/detail.tsx

import React, { useContext } from 'react';
import { View, Text, Button } from 'react-native';
import { AppContext } from '../AppContext';

// Detail画面コンポーネント
// @ts-ignore
function DetailScreen({ navigation }) {
  // コンテキストの取得
  const appContext = useContext(AppContext);
  if (!appContext) return null;
  const { login, setLogin } = appContext;

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Detail画面</Text>
      <Button
        title='Home画面に戻る'
        onPress={() => navigation.goBack()}
      />
      <Text/>
      <Text>
        {login ? 'Login' : 'Logout'}
      </Text>
      <Button
        title={login ? 'Logout' : 'Login'}
        onPress={() => setLogin(!login)} 
      />
    </View>
  );
}

export default DetailScreen;

「Main/home.tsx」と同様です。

(2) 実行。

npm start

状態がデータ共有されていることを確認します。

次回



この記事が気に入ったらサポートをしてみませんか?