【React Native Expo】シンプルなリスト表示と画面遷移

#概要
こんにちは。桜も咲き、少しずつ暖かくなってきましたね。
4月は新しいことを始めたくなる季節です。ということで、まったく初心者がReact Native Expoでアプリ開発していこうじゃ～ないかと思い立ちまして、得た知見をまとめていきたいと思います。

#この記事でわかること
* とってもシンプルなリスト表示
* とってもシンプルな画面遷移

#環境
React Native Expo : 4.3.2
react-navigation/native : 5.9.3
react-navigation/stack : 5.14.3

#作ったもの

![navigation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674937/86262527-5705-c445-ba4e-1f1a33d7ef64.gif)

#ソースコード

```react
import React from 'react';
import {StyleSheet,
  Text,
  View,
  FlatList,
  TouchableHighlight,
} from 'react-native';

// React Navigation Module
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'

const Stack = createStackNavigator()
var Yasai_list = {
  Species : [  
  {id: 1, title: "オクラ"},
  {id: 2, title: "キャベツ"},
  {id: 3, title: "ピーマン"},
  {id: 4, title: "ナス"}
  ]
}

export default class App extends React.Component {
  constructor(props) {
    super(props)
  }

  render(){
    return (
      <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
        <Stack.Screen 
          name="Home" 
          component={HomeScreen} 
        />
        <Stack.Screen 
          name="オクラ" 
          component={DetailsScreen1} 
        />
        <Stack.Screen 
          name="キャベツ" 
          component={DetailsScreen2} 
        />
        <Stack.Screen 
          name="ピーマン" 
          component={DetailsScreen3} 
        />
        <Stack.Screen 
          name="ナス" 
          component={DetailsScreen4} 
        />   
        </Stack.Navigator>
      </NavigationContainer>
    );
  }
}

function HomeScreen({ navigation }) {
  return (
    <View style={styles.container}>
    <FlatList
    data = {Yasai_list.Species}
    renderItem = {({item}) => (
      <TouchableHighlight
        onPress={() => 
          navigation.navigate(item.title)}
          underlayColor={'green'}>
        <View style = {styles.listItem}>
          <Text style = {styles.listTitle}>{item.title}</Text>
        </View>
      </TouchableHighlight>
    )}         
    />
  </View>
  )
}

function DetailsScreen1() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>オクラの子画面だよ</Text>
    </View>
  )
}

function DetailsScreen2() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>キャベツの子画面だよ</Text>
    </View>
  )
}

function DetailsScreen3() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>ピーマンの子画面だよ</Text>
    </View>
  )
}

function DetailsScreen4() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>ナスの子画面だよ</Text>
    </View>
  )
}

 //スタイルシート
 const styles = StyleSheet.create({
  container:{
    width:'100%',
    flex:1,
    marginTop: '30%'
  },
  listItem:{
    padding:20,
    alignItems: 'center',
  },
  listTitle:{
    fontSize:18,
  },
  detail_container:{
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text:{
    fontSize:18,
  }
 });
```
#React-Navigationについて
画面遷移のモジュールとして、react-navigation/native、react-navigation/stackを利用してみました。
react-navigationによって、アプリの画面間を遷移でき、遷移の履歴を管理することができます。
一番シンプルな遷移管理がreact-navigator/stackです。

react-navigator/stackを利用するおまじない。

```react
const Stack = createStackNavigator()
```

#コード解説
一番最初に表示するリストのオブジェクト。
ん？javascriptのオブジェクトの書き方ってどうだっけ？と私はなりました。
復習します。
以下 素晴らしい公式 
https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/Basics を参考

>オブジェクトの初期化 : Yasai_List = {}
オブジェクトには複数のメンバーを追加することができる。
メンバーは、名前と値をセットに持っている。
メンバーの書き方は、「名前 : 値」のように名前と値の間に : を挟む 
今回、Yasai_Listのオブジェクトのメンバーは一つだけで、名前はSpeciesで
値は、リスト表示するための配列を持たせておく。
配列の中には、idとtitleの連想配列を持たせておく。


```react
var Yasai_list = {
  Species : [  
  {id: 1, title: "オクラ"},
  {id: 2, title: "キャベツ"},
  {id: 3, title: "ピーマン"},
  {id: 4, title: "ナス"}
  ]
}
```

React-Nativeを触ってみて一番わからなかったところ。
そう、コンポーネント...きっとこれからも苦しむことになるだろう。

以下 素晴らしい Reactの公式 
https://ja.reactjs.org/docs/components-and-props.html
>コンポーネントにより UI を独立した再利用できる部品に分割し、部品それぞれを分離して考えることができるようになります

なるほど、わからん。
わからんなりにも読んでいくと、どうやら、コンポーネントは2種類あって、
クラスコンポーネントと関数コンポーネントがあって、それぞれ、UIの部品にできるそう。
クラスコンポーネントと関数コンポーネントの違いについては、Reactの重要機能Stateに影響するらしく、
当方、まだ理解できていないため、細かい違いについては、放置しておいて、また戻ってこようと思います。

今回は、クラスコンポーネントをデフォルトとして記述していこうと思います。
クラスコンポーネントには、必ず定義しなければいけない関数 `render`メソッドがあります。

`render`メソッドの機能はというと、コンポーネントをrenderできるということ(？)
先ほどの公式によると、コンポーネントはUIの部品であることから、UIの部品をレンダリングできるのだろう...
なんかわからんけど、すごい。

`render`メソッドの戻り値に、JSXというJavascriptの拡張構文を使ってReact要素を作っていきます。
やはり、どうしても新しいことを勉強すると新しい単語がたくさんでてきてしまうので、少しでも単語の補強をしていこうと思います。

React要素とは 公式によると
>要素とは React アプリケーションの最小単位の構成ブロックです。

深入りすると戻ってこれなくなるので、先に進みます。


```react
export default class App extends React.Component {
  constructor(props) {
    super(props)
  }
  render(){
    return (
      .
      .
      .
  )

```

######renderメソッドの返り値内のコード
以下 素晴らしいReact-Navigationの公式 を参考にしました。
https://reactnavigation.org/docs/hello-react-navigation

公式を要約すると
NavigationContainer内でNavigationを管理できます。
Screenコンポーネントで、各画面のルートを指定します。
とのこと。

今回でいうと、
・ホーム画面のルート
・オクラの子画面ルート
・キャベツの子画面ルート
・ピーマンの子画面ルート
・ナスの子画面ルート
上記5つのルートが必要

各Screenコンポーネントの`name`でルートの名前を設定することができ
`initialRouteName`で初期画面のルートを指定します。
`component`には、ルートに対応する画面の関数コンポーネントを指定します。


```react
     <NavigationContainer>
        <Stack.Navigator initialRouteName="Home">
        <Stack.Screen 
          name="Home" 
          component={HomeScreen} 
        />
        <Stack.Screen 
          name="オクラ" 
          component={DetailsScreen1} 
        />
        <Stack.Screen 
          name="キャベツ" 
          component={DetailsScreen2} 
        />
        <Stack.Screen 
          name="ピーマン" 
          component={DetailsScreen3} 
        />
        <Stack.Screen 
          name="ナス" 
          component={DetailsScreen4} 
        />   
        </Stack.Navigator>
      </NavigationContainer>
```


######ホーム画面の関数コンポーネント　リスト表示
関数コンポーネントには、renderメソッドは必要なく、今回の場合は、return文のみ記述
CSSの記述については、今回は言及しませんので、スルーしてください。

リスト表示については、以下 素晴らしい React Nativeの公式を参考
https://reactnative.dev/docs/flatlist

React Nativeには、シンプルにリストを表示することができるFlatListというコンポーネントがあります。ありがたい。

今回はFlatListコンポーネントには2つのプロパティを利用しています。

1.`data`プロパティ
2.`renderItem`プロパティ

1.`data`プロパティには、リスト表示する内容が格納されているオブジェクト`Yasai_list.Species`を指定しています。

2.`renderItem`プロパティは実際にリストに表示する内容を指定しています。
特に、`item`には自動的に、dataに定義したオブジェクト(`Yasai_list.Species`)の各要素が一つずつ取得されていくようです。
(オクラ、キャベツ、・・・　のように順番に値が入っていくイメージ。)

`renderItem`プロパティに関数を適用しており、`Yasai_list.Species`の各要素ごとに処理が行われていきます。

そして、以下の記事で
[TouchableHighlightを利用して何でもボタンにする](https://qiita.com/zaburo/items/8d9e898f3845e9e293bb)
ボタン以外にもボタン機能をつけることができるコンポーネントがあることを知りました。

`TouchableHighlight`コンポーネントにより、リストの内容をボタンとして扱い、
`onPress`関数内に`navigation.navigate(Screenコンポーネントの名前)`を指定してあげるだけで、リストの内容(ボタン)押下後に指定した画面への遷移ができました。

```react
function HomeScreen({ navigation }) {
  return (
    <View style={styles.container}>
    <FlatList
    data = {Yasai_list.Species}
    renderItem = {({item}) => (
      <TouchableHighlight
        onPress={() => 
          navigation.navigate(item.title)}
          underlayColor={'green'}>
        <View style = {styles.listItem}>
          <Text style = {styles.listTitle}>{item.title}</Text>
        </View>
      </TouchableHighlight>
    )}         
    />
  </View>
  )
}
```


以下子画面のコンポーネントたち

```react
function DetailsScreen1() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>オクラの子画面だよ</Text>
    </View>
  )
}

function DetailsScreen2() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>キャベツの子画面だよ</Text>
    </View>
  )
}

function DetailsScreen3() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>ピーマンの子画面だよ</Text>
    </View>
  )
}

function DetailsScreen4() {
  return (
    <View style={styles.detail_container}>
      <Text style={styles.text}>ナスの子画面だよ</Text>
    </View>
  )
}
```

#まとめ
細かい機能を一つ一つ作るというよりは、細かい機能を実現できるコンポーネントがすでに用意されており、そのコンポーネントの使い方をその都度調べていく必要があることがわかりました。
逆に言えば、一回使えるようになったコンポーネントは部品として使えるため、開発スピードは上がりそうな予感がします。
ありがとうございました。