React Native ハンズオン〜第2回
この資料は React Native Japan主催の新生活応援!React Nativeハンズオン 入門編 #2 の資料です。
主に以下のような内容を扱います。
- React基礎ざっくり(コンポーネント作成, props, stateの利用)
- API通信によるデータ取得
- React Navigationによる画面遷移
最終的にはこのようなニュース閲覧アプリを作成します。
(Udemyコース React Native入門:ニュースアプリを作りながら覚えよう の一部抜粋になります)
0.環境構築
ハンズオン第1回の事前準備編をご参照ください!
Exopo CLI
npm install expo-cli --global
もしくは
yarn global add expo-cli
プロジェクトの作成
expo init hands-on-0418
cd hands-on-0418
yarn start
今回はblankを選択

💡
TypeScriptで書きたい人は blank(TypeScript)を選んでも大丈夫です。
tabsを選ぶと画面下に3つのタブが付いたテンプレートを作成してくれます。Managed Workflowはネイティブ側のコードが触れない代わりに、ネイティブの面倒な作業をExpoが全部肩代わりしてくれる楽なモードです。一方Bare Workflowはネイティブのコードも触れる柔軟性がある代わりに、ビルド作業などはネイティブの知識も必要になります。
シミュレーターを起動

もしくは
# expoサーバー起動&iOSシミュレーター起動
yarn ios
1.ニュースの項目を表示するコンポーネントを作る
1.1 レイアウトを考える
まずはUIを作りながら、ReactNativeのスタイリングに慣れてみましょう。
今回は3つの部分に分けて構成します。
itemContainer: 外枠。横並び。
leftContainer: 左の枠。幅100で固定。
rightContaier: 右の枠。縦並び。flex:1で可能な限り埋める。
<View style={styles.itemContainer}>
<View style={styles.leftContainer}>
{/* 画像 */}
</View>
<View style={styles.rightContainer}>
<Text style={styles.title} numberOfLines={3}>
{/* テキスト 上段 */}
</Text>
<Text style={styles.subTitle}>
{/* テキスト 下段 */}
</Text>
</View>
</View>
| 項目 | 説明 |
|---|---|
| flexDirection | 縦並び(column)か横並び(row)か。デフォルトは縦 |
| alignItems | 並びと垂直方向の配置 |
| justifyContent | 並び方向の配置 |
1.2 ListItemコンポーネントに切り出す
再利用しやすいように別ファイルのcomponentに切り出しましょう。
componentsというフォルダを作って、ListItemというcomponentを作成します。
中身は一旦まるっとコピーましょう。
1.3 propsで情報を渡すように改修
このままではListItemの内容が常に同じなので、再利用できません。
なのでListItemの中身を親から指定できるようにしましょう。そのためにpropsを使います。
あとでstateというものも出てきますが、propsとstateが若干混同しやすいので整理しておきましょう。
propsはコンポーネントの性質を表し、親から与えられる不変な値です。
stateはコンポーネントの状態を表し、その時々で変更できる可変な値です。
ここではListItemに親からpropsとして渡しましょう。
まず引数でpropsを受け取るようにします。
export const ListItem = (props) => {
const { title, subTitle, imageUrl } = props;
or
こう書いてもOK(こちらの方がよくあるパターン)
export const ListItem = ({ title, subTitle, imageUrl }) => {
ハードコーディングしていた部分をprops.imageUriのような形で受け取ったpropsを使って表示するように。
<Image style={{ width: 100, height: 100 }} source={{ uri: imageUrl }} />
親の方でpropsを渡すように。
<ListItem
imageUrl="https://picsum.photos/200"
title="React Native は、Facebookが開発したクロスプラットフォームアプリ開発用フレームワークです。 ReactNative でアプリを作ることで、クロスプラットフォーム( iOS / Androidどちらでも動く)アプリを作ることができます。"
subTitle="Techニュース"
/>
2. APIから記事一覧を取得して表示する
2.1 FlatListで一覧表示する
まず一覧表示の仕組みを作ります。
表示する記事はとりあえずダミーのデータARTICLESを定義しておきます。
FlatListはスクロールする一覧画面などを作成するときに使用します。
ScrollViewというコンポーネントあるけど、FlatListのほうが動作が高速です。
一覧の項目数が多くなる場合はFlatListを使用しましょう。
FlatListのpropsについて
| props | 説明 |
|---|---|
| data | 表示するアイテムの配列 |
| renderItem | アイテムをレンダーする関数 |
| keyExtractor | 各アイテムにユニークなkeyを設定する関数 |
- iPhoneXの対応のため
SafeAreaViewを導入しましょう。上下の余白部分を避けてくれます。
2.2 下準備~ useState, useEffectを使う
先程の例では、記事データをconstで定義していましたが、APIから取得する場合は、取得したデータを変数に格納する必要があります。
この変数は可変な値なのでstateに格納する必要があります。
そこでuseStateというhooksを使います。
useStateを使うと関数コンポーネントにstateを持たせることができます。
また、度のタイミングでAPIを呼ぶかですが、今回はコンポーネントのマウント時にAPIを呼び出したいと思います。
その際に利用するのがuseEffectになります。
(APIを呼び出すような操作を副作用と呼びます)
2.3 APIから記事のデータを取得する
今回のハンズオン用に以下のようなAPIを用意しました。
ブラウザにこのURLを入れるとレスポンスのJSONが確認できます。
[GET] https://asia-northeast1-news-app-udemy.cloudfunctions.net/dummy_news
APIの呼び出しには axiosというライブラリを利用します。
以下コマンドをターミナルに入力してインストールしてください。
yarn add axios
コードの変更は以下になります。
4. ReactNavigationで画面遷移
ルーティングのライブラリは色々あるけど、ExpoではReactNavigationを推奨します。
4.1 ライブラリのインストール
react-navigationのインストール
yarn add @react-navigation/native
Expo managed projectの場合
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
今回はstack navigationという機能を使うため以下をインストール。
yarn add @react-navigation/stack
4.2 今までの画面をHomeScreenに分ける
今まで表示していた画面をHomeScreenという画面として定義して、React Navigationを用いて表示するようにします。
見た目としては今までと変わりません。
参考: https://reactnavigation.org/docs/hello-react-navigation#creating-a-stack-navigator
4.3 DetailScreenを用意し、記事をタップしたら遷移するように
新しくDetailScreenを用意します。
また記事をタップしたら、そのDetailScreenに遷移するようにします。
navigatorにDetailScreenを追加する必要があります。
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
+ <Stack.Screen name="Detail" component={DetailScreen} />
</Stack.Navigator>
<StatusBar style="auto" />
</NavigationContainer>
遷移はnavigation.navigate()で実行できます。
<ListItem
imageUrl={item.urlToImage}
title={item.title}
subTitle={item.author}
+ onPress={() => navigation.navigate('Detail')}
/>
💡
タップ検出にはPressableコンポーネントも使用できます。React Native 0.63から導入され、より細かな制御が可能になっています。
参考:https://reactnavigation.org/docs/navigating
4.4 遷移時にパラメータを渡す
遷移元では、navigate()の第2引数に渡したいパラメータを指定できます。
onPress={() => navigation.navigate('Detail', { article: item })}
遷移先のスクリーンではprops.route.paramsで取得できます。
export default function HomeScreen(props) {
const article = props.route.params.article;
参考:https://reactnavigation.org/docs/params
5. ステップアップ
時間に余裕がある方はチャレンジしてみてください!
5.1 リアルなニュースをAPIで取得する
今回はダミーのニュース取得APIを利用しましたが、リアルなニュースを取得できる無料のAPIがあります。
News API
このNews APIのレスポンスのJSON形式は、今回使用したダミーのAPIと同じなので、スムーズに移行できると思います。
5.2 WebViewでニュースを表示
上記のNews APIを使用すると、記事のURLを取得できます。
DetailScreenでWebViewを用いて、記事のウェブサイトを表示すると、だいぶニュースアプリっぽくなります。
WebView: https://docs.expo.io/versions/latest/sdk/webview/
5.3 ページング
今回はAPIを一度だけ叩いて、1ページ目だけを表示していますが、スクロールに応じて2ページ目以降を表示できるようにしてみましょう。
NewsAPIはpage=2のようなクエリパラメータを渡すと2ページ目以降も取得できます。
またFlatListにはスクロール最下部に達したときにonEndReachedというイベントを発火してくれます。
この辺りを使ってページングを実装してみましょう。
おまけ
今回の内容のベースになっているUdemyコースの方では、さらに reduxの状態管理や、ストア公開についても解説しています。
興味のある方はぜひご覧になって下さい。

Discussion