データ構造を決める
早速メイン画面の作成に入りたいところですが、その前に決めておきたいことがあります。メモのデータ構造です。データ構造を先に決めて、UIの実装はそれに合わせて進めていった方が、アプリの開発はうまく行きやすいのです。というわけで、デザインを観察して、適切なデータ構造について考えてみましょう。以下の図5はメモ1つ分の画面部品について注釈したものです。
この画面部品は「本文」と「作成日時」の2つのデータから成り立っていることがわかります。これをJavaScriptのオブジェクトとして表現すると、リスト2の通りになります。
const memo = { text: "メモメモメモ", // (1) createdAt: 1585567500000, // (2) };
本文を表す(1)の text
は文字列として表現して問題なさそうです。また、作成日時である(2)のcreatedAt
はDate
との相互変換が容易なUNIXタイムスタンプ形式を採用しました。このデータ構造に基づいて、前述のデザインで表示していたメモのリストをデータとして表現すると、リスト3の通りになります。
const memos = [ { text: "メモメモメモ", createdAt: 1585574700000, // 2020.03.30 22:25 }, { text: "メモメモメモ", createdAt: 1585567500000, // 2020.03.30 20:25 }, { text: "長いメモメモメモメモメモメモメモメモメモメモメモメモメモメモ", createdAt: 1585459500000, // 2020.03.29 14:25 }, { text: "メモメモメモ", createdAt: 1585369500000, // 2020.03.28 13:25 }, { text: "メモメモメモ", createdAt: 1585275900000, // 2020.03.27 11:25 }, ];
まずは、このデータを画面に表示することを目指すとよさそうです。
余談になりますが、リスト3のUNIXタイムスタンプはChrome DevToolsのコンソールで図6のようにDate.parse
を地道に実行して作成しました。
React Nativeとブラウザは多くの部分で同じ動きをするため、デバッグにはブラウザの助けを借りると楽な場合があります。
FlatListでリストを画面に表示する
それでは、前節で作成したmemos
をMainScreen
に組み込んでみましょう。リストの表示には、React Nativeでリストを表示する場合によく使われる、FlatList
を採用します。実装はリスト4の通りです。
import React from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { List } from 'react-native-paper'; const memos = [ { text: "メモメモメモ", createdAt: 1585574700000, // 2020.03.30 22:25 }, // 省略 ]; export const MainScreen = () => { return ( <View style={styles.container}> <FlatList style={styles.list} data={memos} // (1) keyExtractor={item => `${item.createdAt}`} // (2) renderItem={({ item }) => ( // (3) <List.Item // (4) title={item.text} description={item.createdAt} /> )} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, }, list: { flex: 1, }, });
FlatList
は配列を並べるためのコンポーネントです。画面外に出たビューを自動で破棄してくれるため、どんなにデータ量が多くても、最小限のメモリで画面を描画できます。
では、FlatListをどのように使っているのかおさらいしましょう。
まずは(1)でdata
属性に配列を登録します。このデータは100件でも1000件でも描画時のメモリ消費には影響しません。
次に、(2)で配列内のデータからキーを生成する際の変換関数を登録します。これは内部でkey
属性として使われる関係で、文字列を返す必要があります。今回は作成日時を文字列に変換して返すことにしました。
続いて、renderItem
属性に、データ1つ分を表示するためのJSXを定義します。1つ分のデータは(3)でitem
という名前で渡されるので、これをUIに変換する形になります。JSXの実装としては、(4)のようにReact Native PaperのList.Item
を使うことにしました。text
とcreatedAt
を、それぞれtitle
属性とdescription
属性に当てはめています。これを実行すると、図7の通りになります。
ところどころに気になるところはありますが、ひとまずデータを並べることには成功したようです。
日時の表記を整える
出しているデータ自体に間違いは無いのですが、表現が想定していたものと違っています。1つずつ正しい表現に直していきましょう。まずは一番気になる、UNIXタイムスタンプのままになっている日時を、デザイン資料通りの表記に直したいところです。
日時データを操作したい場合は、日時に関する便利な関数を寄せ集めたライブラリである、date-fnsが便利です。まずはインストールしましょう(リスト5)。
$ npm install date-fns
インストールが終わったら、renderItem
の実装をリスト6のように修正します。
// 省略 import format from 'date-fns/format'; // (1) // 省略 renderItem={({ item }) => ( <List.Item title={item.text} description={ `作成日時: ${format(item.createdAt, 'yyyy.MM.dd HH:mm')}` // (2) } /> )} // 省略
今回は表現を整形したいので、(1)でformat
関数をインポートしています。(2)ではformat
関数を使って、デザイン資料通りの表記で日時が表示されるようにしました。yyyy.MM.dd hh:mm
という部分はy
が年、M
が月、といった形で、日時データをどんなテキスト表現に落とし込むかを示しています。曜日などもサポートしていて便利なので、気になる方は公式ドキュメントをご覧ください。
さて、これを実行すると図8の通りになります。
これで日時の表記が正しくなりました。date-fnsはDateデータやUNIXタイムスタンプを操作するときに重宝するので、機会があれば使ってみてください。