React Native 入門してみた⑤ データ永続化編

[React Native 入門してみた④ カメラ実装編 - Qiita](https://qiita.com/garbanzo/items/f861982efe2d80e84d84)につづいて今回はデータ永続化についての入門です。

## データ永続化
今回はState管理にReduxを選択しています。
その為、Reduxで利用出来るデータ永続化`redux-persist`にしました。

- [rt2zz/redux-persist: persist and rehydrate a redux store](https://github.com/rt2zz/redux-persist)
 
簡単なカウンターアプリで試してみました。
Reduxの実装部分に関しては説明は省きます。すでにReduxで実装れている前提です。
前回同様、`create-react-app`で作成し、+TypeScript構成です。
また実装は、下記を参考にさせて頂きました。

- [Storeの永続化にredux-persistを使う - Qiita](https://qiita.com/yasuhiro-yamada/items/bd86d7c9f35ebb1c1e7c)
- [ReactNativeでRedux-Persistを使ってみる - Qiita](https://qiita.com/zaburo/items/c3ccfc7c8bf273e9d004)


下記Expoにてサンプル公開してます。

- [CounterApp on Expo](https://expo.io/@garbanzo/CounterApp)


### 実装

```    
.
├── App.tsx
├── app.json
├── assets
├── babel.config.js
├── node_modules
├── package-lock.json
├── package.json
├── src
└── tsconfig.json
```
デフォルトで生成されるファイル達です。
ここで編集するのは`App.tsx`のみです。

```
src
├── Store.ts
├── actions
│   └── CounterAction.tsx
├── components
│   └── Counter.tsx
└── reducers
    └── CounterReducer.tsx
```    

編集するのは、`Store.ts`に`redux-persist`の利用を組み込んで行きます。


#### Store

Store.ts

```Store.ts
import { createStore as reduxCreateStore, combineReducers } from 'redux';
import { reducer, State } from './reducers/CounterReducer';

import { persistReducer, persistStore } from 'redux-persist';
import storage from 'redux-persist/lib/storage';

export type AppState = {
    state: State
};

//persistの設定
const persistConfig = {
    key: 'root',
    storage
}

const createStore = () => {
    const store = reduxCreateStore(
        persistReducer(persistConfig, combineReducers<AppState>({
            state: reducer
        }))
    );
    const persistor = persistStore(store);

    return { store, persistor };
}

export default createStore()
```
まずは、persistConfigをkey名(変更可能)とstorageを指定し作成します。
storageはデフォルト`AsyncStorege`になります。
他の使いたい場合は下記を参照下さい。

- [rt2zz/redux-persist: persist and rehydrate a redux store](https://github.com/rt2zz/redux-persist#storage-engines)

次にreducerとpersistConfigを`redux-persist`が提供する`persistReducer` に指定して作成し、`redux`の`createStore`に渡しstoreを作成します。
生成したstoreを`redux-persist`が提供する`persistStore`に渡しpersistorを作成します。
最後にstoreとpersistorを返却して終わりです。

## App


App.tsx

```
import React from 'react';
import { StyleSheet, View, Button } from 'react-native';
import { Dispatch } from 'redux';
import { Provider, connect } from 'react-redux';
import { Action } from 'typescript-fsa';

import { actions } from './src/actions/CounterAction';
import Counter from "./src/components/Counter"

import Store, { AppState } from "./src/Store"

// Connect
function mapStateToProps(appState: AppState) {
  return Object.assign({}, appState.state);
}

function mapDispatchToProps(dispatch: Dispatch<Action<any>>) {
  return {
    update: (v: number) => dispatch(actions.update(v)),
  };
}

const MyAPP = connect(mapStateToProps, mapDispatchToProps)(Counter);

//APP
export default class App extends React.Component {

  render() {
    return (
      <Provider store={Store.store}>
        <View style={styles.container}>
          <MyAPP />
          <Button title="Purge" onPress={() => Store.persistor.purge()} />
        </View>
      </Provider>
    );
  }
}

...
```
先程作成したStoreをimportして、`Provider`に渡せば完了です。
`persistor`に様々な関数が用意されており、`purge()`はデータを一括削除出来ます。
上記実装の場合、ボタンを押しただけでは更新されません。
リロードして下さい。リセットされるはずです。

また、AsyncStore保存されたデータが確認したい場合は下記で確認出来ます

```
import { AsyncStorage } from 'react-native'

async getDate() {
    const keys = await AsyncStorage.getAllKeys();
    console.log(keys);
    // keysがN件ある場合は、引数変更して下さい。
    const value = await AsyncStorage.getItem(keys[0]);
    console.log(value);
}

this.getDate()
```

## Next
検討中です。