この記事の続き。
前回はハードコーディングされた東京の天気予報を表示していたが、今回はリストからユーザーに選ばせた場所の天気予報や、位置情報取得APIを利用して現在地の天気を表示していく。
[県名リストを表示する]
まずは、県名データを作成する。
ここも写経だから……と思ったが、いくら深夜のテンションでも47都道府県の県名を漢字とアルファベットで打ち込んでいくのは辛い……。
記事の誘惑に負けて、 GitHubのリポジトリからjsonデータを取得させていただくことに。
jsonから読み込んだデータを元に、FlatListをいうコンポーネントを利用して一覧画面を作っていく。
一覧画面から、前回実装した天気予報画面への遷移には、react-navigationというライブラリを使う。
公式サイトには実装したデモ動画が載っていて、普段使っているようなネイティブアプリっぽい画面遷移が実現できることが分かる。これはぜひ覚えて使いこなしたいところ。
そういえば、react-native-webとかっていうReact Nativeのコードをブラウザで使いまわすためのライブラリの話を聞いたことがあるけれど、React Navigationも使えるのだろうか。だとしたらモバイルブラウザ対応とか結構楽にできる気がする。
で、一覧が表示されるはず、と思ってシミュレータを起動するも、何も表示されない。
何日かかけて記事中に記載されているコードと自分が写経したコードを見比べて、ようやく( ... )
が{ ... }
となっている部分を発見し、修正したところようやく一覧画面が表示された。
Webdb102Weather/CityListScreen.js at master · kdnakt/Webdb102Weather · GitHub
ここが問題の箇所。
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => this.onPress(item)}
style={styles.itemContainer}
>
<Text style={styles.text}>
{item.name}
</Text>
</TouchableOpacity>
)}
となっているのが正しいのだが、写経したコードは以下のようになっていた。
renderItem={({ item }) => {
<TouchableOpacity
onPress={() => this.onPress(item)}
style={styles.itemContainer}
>
<Text style={styles.text}>
{item.name}
</Text>
</TouchableOpacity>
}}
勘違いして写経した原因はおそらく、アロー関数で複数行の式を実行する必要があるから、と思ってブラケットで書き始めた、ということだと思われる。実際にはReactコンポーネントをreturnしているだけなので括弧の方が正しかったというわけ。
残りの、一覧画面から天気予報画面への遷移は特に問題なく実装して終了。
[現在地情報を取得する]
現在地情報を取得するには、iOSの場合はInfo.plistに取得理由を、Androidの場合はAndroidManifest.xmlに利用する権限を記載すればいけるらしい。
この辺は難なくクリア。
ここまでで、第3章の写経は終わり。
[jestによるスナップショットテスト]
ここからは記事にないけど気になったのでやってみる。
第2章を参考に、__tests__/App.js
にスナップショットテストを実装しnpm test
コマンドを叩いて、jestのテストを走らせる、とエラー。
公式サイトによれば、トランスパイルされていないjsはエラーになるので、transformIgnorePatterns
オプションを指定して対応せよとのこと。指示通り、
package.json
でjestの設定を変えると、問題なくスナップショットファイルが作成された。
しかし、戯れにそのまま2回目のスナップショットテストを実行すると、何とスナップショットが変更されていると判定され、テストが失敗してしまった。
どうやらどこかのキーが毎回実行時に変わるようだ。
react-navigation
に問題がありそうだったので、ソースを読んでみると、react-navigation/src/routers/StackRouter.js
の_getUuid()
をモックすればスナップショットテストを通せそうだと分かった。
const uniqueBaseId = `id-${Date.now()}`; let uuidCount = 0; function _getUuid() { return `${uniqueBaseId}-${uuidCount++}`; }
何かいい方法はないか、とググったところ、またしても公式サイトがヒットした。
Date.now = jest.fn(() => 1482363367071);
を試すがダメ。恐らく、モックする以前にconst uniqueBaseId = `id-${Date.now()}`;
でDate.now()
が実行されているためと思われる。
さらにググって見つけたこちらの手法で対応することに。keyが邪魔ならkeyを除外すればいいじゃん、という。
そのままだとスナップショットオブジェクトの構造に合わず、keyをフィルタリングできなかったので、ちょっと改造して、無事keyをスナップショットから除外することに成功。
これで何度テストを実行しても大丈夫!
[まとめ]
実装した結果はこちら。
何とか新しい号のWEB+DB PRESSが出る前に写経を完了できた。
第4章は写経できなそうだけど、CodePushとか実際に触ってみたい。