react-nativeでstorageを使おうとすると、cosole.errorが出てしまう

#はじめに

![スクリーンショット 2019-09-03 10.20.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/1a1c8890-70a7-7539-7444-60c41bf9756f.png)
<a href="https://www.amazon.co.jp/React-Native-Expo%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%82%B9%E3%83%9E%E3%83%9B%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA-JavaScript%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA%E6%A7%8B%E7%AF%89%E3%81%AE%E5%AE%9F%E9%9A%9B-%E6%9D%BE%E6%BE%A4/dp/4839966648"target="_brank">ReactNative+Exoiで始めるスマホアプリ開発</a>



この本の第７章、React Nativeの状態管理のなかでデータの永続性（保存）
に触れられた部分で、エラーが出てしまい、先に進めなくなってしまった。
そこで、これの解決策を示すことで、後からこの学習に取り組む若者たちの手助けとなるような記事を書いていきたい

#　作りたいアプリ
単純なTodoアプリで
検索フィールド、スクロールフィールド、入力フォームがあるアプリ、図にするとこんな感じ↓
![IMG_3007.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/e7e1c49c-3a9b-ec54-782b-dddd38d21d27.jpeg)


# コード
```App.js
import {createStore} from 'redux'
import {persistReducer,persistStore} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import rootReducer from './rootReducer'


const persistConfig ={
    key: 'TODO',
    storage,
    whitelist:['todos'.currentIndex]
}
const persistedReducer = persistReducer(persistConfig,rootReducer)
const store = createStore(persistedReducer)


export const persistor = persistStore(store)
export default store
```

```src/actionCreator.js
import {TODO} from './actions'
export const addTodo = (text) =>{
    return {
        type:TODO.ADD,
        text,
    }
}
export const toggleTodo = (todo) => {
    return {
        type:TODO.TOGGLE,
        todo
    }
}
```

```src/action.js
export const TODO ={
    Add:'TODO_APP',
    TOGGLE:'TODO_TOGGLE',
}
```

```src/rootReducer.js
import { combineReducers} from 'redux'
import todoReducer from './todoReducer'

export default combineReducers({
    todos:todoReducer
})
```

```src/store.js

import {createStore} from 'redux'
import {persistReducer,persistStore} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import rootReducer from './rootReducer'


const persistConfig ={
    key: 'TODO',
    storage,
    whitelist:['todos'.currentIndex]
}
const persistedReducer = persistReducer(persistConfig,rootReducer)
const store = createStore(persistedReducer)


export const persistor = persistStore(store)
export default store
```

```src/todoReducer.js
import {TODO} from './actions'

const initialState = {
  todos:[],
  currentIndex:0,
  }

  const todos = (state = initialState,action) =>{
    switch(action.type){
      case TODO.ADD:
        const newTodo = {title:action.text,index:state.currentIndex,done:false}
        return {
          ...state,
          todos:[...state.todos,newTodo],
          currentIndex:state.currentIndex + 1
        }
        case TODO.TOGGLE:
          const todoItem = action.todo
          const todos = Object.assign([],state.todos)
          const index = todos.indexOf(todoItem)
          todoItem.done = !todoItem.done
          todos[index] = todoItem
          return {
            ...state,
            todos:todos
          }
        default:
          return state
    }
  }
  export default todos
```

```src/TodoScreen.js
import React from 'react';
import { 
  StyleSheet, 
  Text, 
  View,
  StatusBar, 
  Platform, 
  ScrollView,
  FlatList,
  KeyboardAvoidingView,
  AsyncStrage,
  TouchableOpacity,
} from 'react-native';

import {
  SearchBar,
  Input,
  Button,
  ListItem,
} from 'react-native-elements';

import Icon from 'react-native-vector-icons/Feather';
import Icon2 from 'react-native-vector-icons/MaterialIcons';

import {ifIphoneX,getStatisBarHeight, getStatusBarHeight} from 'react-native-iphone-x-helper';

import {connect} from 'react-redux'
import {addTodo,ToggleTodo, toggleTodo} from './actionCreators'
const TODO = "@todoapp.todo"

// iPhoneX対応
const STATUSBAR_HEIGHT = getStatusBarHeight()

const TodoItem =(props) =>{
  // let textStyle = styles.todoItem
  // if(props.done === true){
  //   textStyle = styles.todoItemDone
  // }
  let icon = null
  if ( props.done == true){
    icon = <Icon2 name="done" />
  }
  return (
    <TouchableOpacity onPress={props.onTapTodoItem}>
      {/* <Text style={textStyle}>{props.title}</Text> */}
      <ListItem
        title={props.title}
        rightIcon={icon}
        bottomDivider
        />
    </TouchableOpacity>
  )
}
class TodoScreen  extends React.Component {

  constructor(props){
    super(props);
    this.state = {
      inputText:"",
      filterText:"",
    }
  }
  onAddItem = () => {
    const title = this.state.inputText
    if(title == "" ){
      return
    }
    this.props.addTodo(title)
    this.setState({
      inputTexxt:""
    })
  }
  
  onTapTodoItem= (todoItem)=>{
    this.props.ToggleTodo(todoItem)
  }
  render() {
    const filterText = this.state.filterText
    let todo = this.props.todo
    if(filterText !== ""){
      todo = todo.filter(t=>t.title.includes(filterText))
    }
    
    const platform = Platform.os == 'ios' ? 'ios' : 'android'

    return (
      <KeyboardAvoidingView style={styles.container} behavior="padding">
        <SearchBar
          platform={platform}
          cancelButtontTitle='Cancel'
          onChangeText = {(text) => this.setState({filterText: text})}
          onClear={()=>this.setState({filterText:''})}
          value={this.state.filterText}
          placeholder='Type filter text'
          />
        <ScrollView style={styles.todolist}>
          <FlatList data={todo}
            extraData={this.state}
            renderItem={({item}) => 
              <TodoItem
                title={item.title}
                done={item.done}
                onTapTodoItem={()=>this.onTapTodoItem(item)}
                />
            }
            keyExtractor={(item, index) => "todo_" + item.index} 
          />
        </ScrollView>
        <View style={styles.input}>
          <Input
            onChangeText={(text) => this.setState({inputText:text})}
            value={this.state.inputText}
            style={styles.inputText}
          />
          <Button
            icon={
              <Icon
                name='plus'
                size={30}
                color="white"
              />
            }
            onPress={this.onAddItem}
            title=""
            buttonStyle={styles.inputButton}
          />
        </View>
      </KeyboardAvoidingView>
    );
  }
}
const mapStateToProps = state =>{
  return {
    todo:state.todos.todos,
  }
}

const mapDispatchToProps = dispatch =>{
  return {
    addTodo(text){
      dispatch(addTodo(text))
    },
    ToggleTodo(todo){
      dispatch(toggleTodo(todo))
    }
  }
}
export default connect(mapStateToProps,mapDispatchToProps)(TodoScreen)
const styles = StyleSheet.create({
  input:{
    ...ifIphoneX({
      paddingBottom:30,
      height:80
    },{
      height:50,
      }),
      height:70,
      flexDirection:'row',
      paddingRight:10,

  },
  inputText:{
    paddingLeft:10,
    paddingRight:10,
    flex:1,
  },
  inputButton:{
    width:48,
    height:48,
    borderWidth:0,
    borderColor:'transparent',
    borderRadius:48,
    backgroundColor:'#ff6347',
  },
  container:{
    flex:1,
    backgroundColor:'#fff',
    paddingTop:STATUSBAR_HEIGHT ,
  },
  // 追加したUIのスタイル
  filter:{![スクリーンショット 2019-09-03 10.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/7a70e98c-3bee-3fda-7fac-17e00d609c09.png)

    height:30,
  },
  inputText:{
    flex:1,
  },

  todoItem:{
    fontSize:20,
    backgroundColor:"white"
  },
  todoItemDone:{
    fontSize:20,
    backgroundColor:"tomato"
  },
});
```

# 出てきたエラー
![スクリーンショット 2019-09-03 10.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/1fa80931-d8bd-3deb-a245-e3eba95041df.png)

よく見てみると
App.js:4<unknown>
store.js:3<unknown>とある。

それぞれ該当箇所を抜き出してみると

```App.js
{/*4行目*/}
import store,{persistor} from "./src/store"
```

```store.js
{/*3行目*/}
import storage from 'redux-persist/lib/storage'
```

どうやら、redux-persistを使うところでエラーが出ている模様。

なので。
redux-persistを追加する

```
npm install redux-persist --save
```

した後、プロジェクトを立ち上げ、エミュレータを起動してみると
![スクリーンショット 2019-09-03 10.54.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/4882218e-aa61-5bfd-6b1e-6a032c499599.png)

結果かわらず😞

いろいろ調べてみると、どうもコマンドが悪かったようで、
https://github.com/irisAsh/learnreactlibrary/wiki/redux_persist
を参考に
```
yarn add redux-persist
```

でやってみると
![スクリーンショット 2019-09-03 10.58.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/cfc49c73-3e45-bf4d-e254-c719fd35dd57.png)

エラーが変わった☺️


もう一回
```
yarn add redux-persist
```
をやってみると、アプリが表示できた。
![スクリーンショット 2019-09-03 11.11.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/be4ddacf-fe1c-edb9-0ae2-42b04a4509d9.png)

ただ、下の入力フィールドにテキスト入力後、保存ボタン（右のオレンジ）を押すと
またしてもエラーが
![スクリーンショット 2019-09-03 11.10.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/793d889a-3173-c32c-6eeb-f5846c8505f9.png)

ここで、全てのコードを見直してみたところ、以下の間違いに気づいた

```src/TodoScreen.js
inputTexxt →　inputText
ToggleTodo →  toggleTodo
props.todo →　props.todos
```

```src/store.js
.currentIndex →　,'currentIndex'
```

```src/action.js
Add →　ADD
```

これを直してプロジェクトを再度立ち上げてみると、エラーが出なくなった。

最初の
![スクリーンショット 2019-09-03 10.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343721/7d663725-cb29-6a0a-f585-8aabe6e55d14.png)

は出るが、これはDismissで抜けられることが判明したので、解決ということにしておく