NCMBのReact Native SDKを使ってカメラメモアプリを作る（その3：データの取得と写真のダウンロードについて）

NCMBでは公式SDKの他、コミュニティSDKとして各種言語、フレームワーク向けにSDKを提供しています。今回はReact Native SDKを使ったカメラメモアプリ開発を解説します。カメラで写真を撮影して、そこに説明を付けて保存できるというアプリです。ファイルストアとデータストアの機能を利用します。

[前回は写真の撮影と、データの保存について解説](https://qiita.com/goofmint/items/7ee2c256902416e089a4)しました。今回は保存したデータの取得と、写真のダウンロードについて解説します。

## コードについて

今回のコードは[NCMBMania/react-native-camera-app: React Native SDKを使ったカメラメモアプリのデモです](https://github.com/NCMBMania/react-native-camera-app)にアップロードしてあります。また、Expo Snackでも使用できます。

[カメラメモアプリ](https://snack.expo.dev/@git/github.com/NCMBMania/react-native-camera-app)

※ Expo SnackのWebの場合、アイコン表示と画像のリスト表示に不具合があります

## データの取得と表示について

![FireShot Capture 102 - メモ詳細 - localhost 20211013111646 - 102.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2e039987-bd5d-5985-6021-fb98e54af2c7.jpeg)


保存したメモデータの取得はListScreen.jsにて行います。実際にはMemoList.jsを呼び出して、そこで実行しています。

```js
export default function MemoList({ navigation }) {
  // メモ一覧用の変数
  const [memos, setMemos] = useState([]);

  // 最初に一回だけ実行する関数
  useEffect(() => {
    fetchMemo();
  }, []);

  // 表示内容
  return (
    <View style={styles.container}>
      <List.Section>
        <FlatList
          data={memos}
          renderItem={({index, item }) => <Memo
            item={item}
            index={index}
            navigation={navigation}
          />}
          keyExtractor={item => item.get('objectId')}
        />
      </List.Section>
    </View>
  )
}
```

### データの取得

データの取得はfetchMemo関数にて行います。データの取得はNCMBQueryオブジェクトを利用します。今回は条件を付けていませんが、以上や以下、配列に関する条件など細かい絞り込みも指定できます。

結果はsetMemosを使って配列に反映します。

```js
// メモの一覧を取得する関数
const fetchMemo = async () => {
  // NCMBQuery（データストア検索用）のオブジェクトを準備
  const query = new NCMBQuery('Memo');
  // 検索実行
  const ary = await query.fetchAll();
  // セット
  setMemos(ary);
};
```

### データの表示

メモの配列はFlatListを使って表示しています。個々のメモはMemo.jsにて描画しています。

```js
export default function Memo({ navigation, index, item }) {
  // 画像のURI（dataURI）が入る
  const [uri, setUri] = useState(null);

  // 最初に1回だけ実行する関数
  useEffect(() => {
    fetchPhoto(); // 写真を取得
  }, []);

  // 表示内容
  return (
    <List.Item
      title={item.get('text')}
      // リストをタップしたら、編集画面に遷移する
      onPress={() => navigation.push('Detail', { item, uri })}
      // タスクの完了状態を見てチェックボックスを変更
      left={props => <Image
          source={{ uri }}
          // チェックボックスをタップしたら、完了状態を反転
          style={{ height: null, width: 100, resizeMode: 'contain' }}
        />
      }
      // > を表示
      right={props => <List.Icon
          icon="chevron-right"        
        />
      }
    />
  )
}
```

表示されるタイミングで、fetchPhoto関数を実行しています。これは、写真データをファイルストアからダウンロードする関数です。

```js
// 画像を取得する処理
const fetchPhoto = async () => {
  // ファイルストアのオブジェクトを準備
  const file = new NCMBFile();
  // ファイル名を設定
  file.set('fileName', item.get('fileName'));
  // ダウンロード実行
  try {
    const uri = await file.download('datauri');
    setUri(uri);
  } catch (e) {
    console.log(e);
  }
};
```

downloadは3つのフォーマットが指定できます。`text` はテキストデータ用（デフォルト）、`binary` はバイナリデータ、 `datauri` はdataURI形式での取得が可能です。

React Nativeの場合、binaryデータをそのまま表示に使えないようなので、dataURI形式にするのが良いでしょう。また、ファイルストアにはHTTPS経由でファイルを取得可能にするオプションもあります。こちらの場合はURLを指定するだけで表示を完結できます。

## 詳細表示について

![FireShot Capture 102 - メモ詳細 - localhost 20211013111647 - 102.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/c56f8cdf-5f19-a257-4591-3ed31feaf57f.jpeg)


一覧からメモをタップすると、詳細画面に遷移します。これは `DetailScreen.js` と `Detail.js` で行っています。ここでは一覧で読み込んでいるメモデータと画像データを、そのまま表示に利用しています。

```js
export default function Detail({ route }) {
  // 一覧画面から渡されるデータ
  const { item, uri } = route.params;
  // 描画内容
  return (
    <View>
      <View style={styles.container}>
        <Image
          source={{ uri }}
          style={{ height: 300, width: '100%', resizeMode: 'contain' }}
        />
      </View>
      <View style={styles.text}>
        <Text>{ item.get('text')}</Text>
      </View>
    </View>
  )
}
```

これでカメラメモアプリの完成です。

## まとめ

今回は実装していませんが、NCMBを使えば認証やデータの更新、削除などの機能を付けることも難しくありません。ぜひそうした機能を使って、より高度なアプリを実現してください。

[NCMBMania/ncmb-react-native: NCMB SDK for React Native](https://github.com/NCMBMania/ncmb-react-native)

## おまけ

NCMBのReact Native SDKを使ったハンズオンは随時開催しています。ぜひチェックしてください。

[【お昼のハンズオン】React Native × NCMBでTodoアプリを作ろう \- connpass](https://ncmb.connpass.com/) など