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 | 並び方向の配置 |
ListItem
コンポーネントに切り出す
1.2 再利用しやすいように別ファイルの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
を導入しましょう。上下の余白部分を避けてくれます。
useState
, useEffect
を使う
2.2 下準備~ 先程の例では、記事データを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