NCMBのReact Native SDKを使ってTodoアプリを作る（その1：画面の説明とSDKの導入）

NCMBでは公式SDKの他、コミュニティSDKとして各種言語、フレームワーク向けにSDKを提供しています。今回はReact Native SDKを使ったTodoアプリ開発を解説します。

今回は各画面やコンポーネントの説明、そしてSDKの導入方法について解説します。

## コードについて

今回のコードは[NCMBMania/Expo-Todo-App: React Native SDKで作ったTodoアプリです](https://github.com/NCMBMania/Expo-Todo-App)にアップロードしてあります。また、Expo Snackでも使用できます。

[NCMB-Expo-Todo-App - Snack](https://snack.expo.dev/@goofmint/1706f4)

## 利用技術について

今回は次のような組み合わせになっています。

- React Native 42.0.0
- Expo 42.0.1
- [NCMB React Native SDK](https://github.com/NCMBMania/ncmb-react-native) 2.0.13

## 仕様について

今回はシンプルにするために認証は利用していません。複数人で利用される場合などは、ID/パスワード認証を利用すると良いでしょう。

## 利用する機能について

Todoアプリで利用するNCMBの機能は次の通りです。

- データストア
  - Todoデータの保存
  - Todoデータの更新
  - Todoデータの削除

## 画面について

今回は2つの画面、6つのコンポーネントを利用しています。

### HomeScreen

Todoの一覧表示、新規作成を行う画面です。

![FireShot Capture 097 - タスクの編集 - localhost 20211011161343 - 097.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/14cc104e-b61d-0d4f-92ba-ad91cab1c2a3.jpeg)


```js
const HomeScreen = ({ navigation }) => {
  return (
    <View style={styles.container}>
      <Text style={styles.paragraph}>
        タスクを追加、編集してください
      </Text>
      <Card>
        <Home navigation={navigation} />
      </Card>
    </View>
  );
}
```

#### Homeコンポーネント

タスクの一覧表示を行います。

```js
// 描画
return (
  <View style={styles.container}>
    <List.Section>
      <List.Subheader>
        <View style={{ flexDirection: 'row'}}>
          <Text>既存のタスク</Text>
          <View
            style={{flexDirection: 'row', justifyContent: 'flex-end' }}
          >
            <ShowDelete />
          </View>
        </View>
      </List.Subheader>
      <FlatList
        data={ary}
        renderItem={({index, item }) => <TodoItem
          item={item}
          index={index}
          navigation={navigation}
          updated={updated}
        />}
        keyExtractor={item => item.get('objectId')}
      />
    </List.Section>      
    <InputTodo added={added} />
    <Text>{ show }</Text>
    <Banner
      message={message}
      show={show}
    />
  </View>
);
```

#### ShowDeleteコンポーネント

![FireShot Capture 097 - タスクの編集 - localhost 20211011161344 - 097.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/6052c826-7bf4-82cc-7ba1-acb647ddc147.jpeg)


タスクを一つでも選択（終了状態）にすると、ボタンを押せる状態にします。

```js
const ShowDelete = () => {
  return (
    <Button
      icon="delete"
      mode="contained"
      onPress={deleteTask}
      // 1件でも完了したタスクがあれば、削除を表示
      disabled={!(ary.filter(item => item.get('checked')).length > 0)}
    >
      <Text>削除</Text>
    </Button>
  )
};
```

#### Inputコンポーネント

タスクの入力と、新規作成を行うコンポーネントです。

```js
return (
  <View style={styles.container}>
    <TextInput
      label="タスク"
      mode="flat"
      dense="true"
      style={styles.textInput}
      value={text}
      onChangeText={(text) => setText(text)}
      onKeyPress={keyPress}
    />
  </View>
);
```

#### TodoItemコンポーネント

リスト表示時の一行あたりのコンポーネントです。

```js
// リスト（各行）の表示処理
return (<List.Item
  title={item.get('body')}
  // リストをタップしたら、編集画面に遷移する
  onPress={() => navigation.push('Detail', { index, item, updated })}
  // タスクの完了状態を見てチェックボックスを変更
  left={props => <Checkbox
    status={item.get('checked') ? 'checked' : 'unchecked'}
    // チェックボックスをタップしたら、完了状態を反転
    onPress={() => checked({index, item})}
    />
  }
  // > を表示
  right={props => <List.Icon
      icon="chevron-right"        
    />
  }
/>)
```

### EditScreen

![FireShot Capture 097 - タスクの編集 - localhost 20211011161345 - 097.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/aa085977-0795-bbb4-f6bc-79894aed144e.jpeg)


Todoの編集を行う画面です。

```js
// 編集画面用
const EditScreen = (props) => {
  return (<View style={styles.container}>
      <Text style={styles.paragraph}>
        タスクを編集してください
      </Text>
      <Card>
        <Edit {...props} />
      </Card>
    </View>
  )
}
```

#### Editコンポーネント

選択されたタスクを表示、編集するコンポーネントです。

```js
return (
  <View style={styles.container}>
    <TextInput
      label="タスク"
      mode="flat"
      dense="true"
      value={text}
      style={styles.textInput}
      onChangeText={(text) => setText(text)}
      onKeyPress={keyPress}
    />
  </View>
);
```

### 追加のコンポーネント

追加としてcomponents/Banner.jsを作成します。これは、Snackbarコンポーネントを使って処理結果の通知に利用します。

```js
return (
  <Snackbar
    visible={visible}
    onDismiss={() => setVisible(false)}
    duration="2000"
    action={{
      label: 'OK',
      onPress: () => setVisible(false)
    }}>
    {message}
  </Snackbar>
);
```

## NCMBの初期化

React Native用のSDKを読み込みます。

```
npm i ncmb-react-native
```

### ncmb.jsの作成

componentsの中に ncmb.js を作成します。ここではReact Native SDKを読み込み、初期化を行います。

```js
import NCMB, { NCMBObject, NCMBQuery, NCMBUser, NCMBAcl } from 'ncmb-react-native';
import config from '../app.json';

// NCMBの初期化
new NCMB(config.applicationKey, config.clientKey);
```

後は同じ内容で返します。

```js
export default NCMB;
export {
  NCMBObject,
  NCMBQuery,
  NCMBUser,
  NCMBAcl,
};
```

app.jsonは次のような内容です。

```json
{
  "applicationKey": "YOUR_APPLICATION_KEY",
  "clientKey": "YOUR_CLIENT_KEY"
}
```

これでncmb.jsを読み込めば、初期化済みのReact Native SDKを利用できます。

## まとめ

今回は画面の説明と、NCMBのSDKを初期化する手順を紹介しました。次回はタスクの新規作成と一覧表示を行う手順を解説します。

## おまけ

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

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