React Nativeでredux-persistを簡単に導入

React Nativeでアプリを開発するときに、デバイスのストレージにデータを保存したいときに、Storeの永続化に使えるredux-persistが便利です。
しかし、さほど複雑なデータを扱わなくとも、Reduxの導入が必須になります。
個人的には、Reduxを導入するには複雑なファイル群がどうしてもハードル高く思ってしまいました。
[世界一シンプルなReactNative + Reduxチュートリアル①](https://qiita.com/kaba/items/8c46767413a3c8d15f00)
この記事を参考して、とってもシンプルにReduxを導入できました。
とっても助かりました。

上記踏まえて、
・ インターフェイス上1Tapで複数のStateを変更するイベント処理をView側の関数に入れて、一旦中継してからStoreへ渡すようにする
・ redux-persistの導入を加える

ことを加味したコードの一部をご紹介します。

## 事前準備
必要なライブラリをインストール

```
npm install --save redux react-redux redux-persist react-native-asyncstorage
```

## コード部分

### redux部分
actions.js, reducers.js, store.jsを一つのファイルにまとめます
redux-persistを導入し、AsyncStorageに保存します。

```redux.js
// redux.js
import { combineReducers, createStore } from 'redux';
import { persistReducer, persistStore } from 'redux-persist';
import { AsyncStorage } from 'react-native';

// actions.js
export const addItem = (inputText1, inputText2) => ({
  type: 'ADD_ITEM',
  inputText1: inputText1,
  inputText2: inputText2
});

export const deleteItem = (targetIndex) => ({
  type: 'DELETE_ITEM',
  targetIndex: targetIndex
});

const INITIAL_STATE = {
  listData: [],
  currentIndex: 0,
}

// reducers.js
const reducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case 'ADD_ITEM':
      const newList = {
        inputText1: action.inputText1,
        inputText2: action.inputText2,
        key: state.currentIndex + 1
      }
      return {
        ...state,
        listData: [...state.listData, newList],
        currentIndex: state.currentIndex + 1
      }
    case 'DELETE_ITEM':
      const targetIndex = action.targetIndex + 1;
      console.log(targetIndex)
      const newlistData = state.listData.filter(function(v){
        return v.key != targetIndex;
      });
      console.log(newlistData)
      return {
        ...state,
        listData: newlistData,
      }

    default:
      return state;
  }
}

export const reducers = combineReducers({
  listData: reducer
})

// store.js
const persistConfig = {
  key: 'MAIN',
  storage: AsyncStorage,
}

const persistedReducer = persistReducer(persistConfig, reducers)
const store = createStore(persistedReducer)
export const persistor = persistStore(store)
export default store
console.log(store)
```
### スクリーンの部分
一部のStoreには渡さないstateのイベントはここの中で完結します。

```Screen.js
import React from 'react';
import { Text, View, ScrollView, FlatList } from 'react-native';
import { Input, Button, ListItem } from 'react-native-elements';
import { connect } from 'react-redux';
import { addItem, deleteItem } from './redux';
import { store } from './redux';

class MainScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputText1: "",
      imageText2: "",
      targetIndex: ""
    };
  }
  addData = () => {
     this.props.addItem(this.state.inputText1, this.state.inputText2)
     this.setState({inputText: "", imageUrl: ""});
   }
   deleteData = (item) => {
     const targetIndex = item.key - 1;
     this.props.deleteItem(targetIndex)
   }

  render() {
    let listContents = this.props.listData;
    return (
      <React.Fragment>
        <ScrollView>
        <FlatList data={listContents}
          extraData={this.state}
          renderItem={({item}) =>
            <ListItem key={"listItem_" + item.key} title={item.inputText1 + item.inputText2} onPress={() => this.deleteData(item)} />
          }
          keyExtractor={(item, index) => "todo_" + item.index}
        />
      </ScrollView>
      <View>
        <Input
          onChangeText={(text) => this.setState({inputText1: text})}
          value={this.state.inputText1}
          keyboardType="default"
          returnKeyType="done"
        />
        <Input
          onChangeText={(text) => this.setState({inputText2: text})}
          value={this.state.inputText2}
          keyboardType="default"
          returnKeyType="done"
        />
        <Button title="Add" onPress={this.addData} />
      </View>
    </React.Fragment>);
  }
}

const mapStateToProps = state => ({
  listData: state.listData.listData
})

const mapDispatchToProps = {
  addItem,
  deleteItem
}

export default connect(mapStateToProps, mapDispatchToProps)(Screen)

```
### 書き出す部分
必要なものをインポートし、PersistGateを加えます。

```App.js
import React from 'react';
import { Provider } from "react-redux";
import store, { persistor } from "./redux";
import { PersistGate } from 'redux-persist/integration/react'
import MainScreen from './Screen';

export default class App extends React.Component {
  render () {
    return (
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <Screen />
        </PersistGate>
      </Provider>
    )
  }
}

```