Redux ExampleのTodoListをReact Native（expo）に置き換えて解説-ToggleTodo編

Redux ExampleのTodoListをReact Native（expo）に置き換えて解説のToggleTodo編です。
AddTodo編は以下です。
[Redux ExampleのTodoListをReact Native（expo）に置き換えて解説AddTodo編](https://qiita.com/tenshinhan_yamucha/items/93307c46bd6c7b3c1652)

注：僕は掛け出しエンジニアであり、自分の勉強としての投稿という面もあるので、もしミスや勘違い、ベストプラクティスではない、等がありましたら、コメントしていただけると幸いです。

#TODOに属性を追加
まずは、todoにcomplete属性を追加してtodoが完了済みなのかactive状態なのかを判定できるようにします。初期値はfalseにしておきます。

```reducers/todos.js
const todoReducers = (state = [], action) => {
    switch(action.type){
        case 'ADD_TODO':
            return [
                ...state,
                {
                    id: action.id,
                    text: action.text,
                    completed: false //追加
                }
            ]
        default:
            return state
    }
}

export default todoReducers

```

Todoのcompleted属性がtrueかfalseによって見た目を変えたいので、TodoListコンポーネントを修正します。

```components/TodoList.js
class TodoList extends Component {
  render() {
    return (
      <View>
        <FlatList
          data={this.props.todos}
          renderItem={({ item }) => (
            <View style={styles.todoList}>
              <Text
                style={{　
                 textDecorationLine: item.completed ? "line-through" : "none",
                }}　//追加↑
              >
                {item.text}
              </Text>
            </View>
          )}
          keyExtractor={(item) => item.id.toString()}
        />
      </View>
    );
  }
}

```
ここで、動作確認のため、reducers/todos.jsのcompleted属性をtrueにしてみましょう。todoに斜線が引かれていると思います。

#Actionからcompleted属性を操作する
次に、上記でやったtrue,falseの操作をActionを経由して操作できるようにしましょう。

まずはActionCreatorを作成します。どのtodoに横線を引くかを判別するためにidを取得します。

```src/actions/index.js

let nextTodoId = 0
export const addTodo = text => ({
    type: 'ADD_TODO',
    id: nextTodoId++,
    text
})    

//追加
export const toggleTodo = (id) => {
  return {
    type: "TOGGLE_TODO",
    id,
  };
};

```

reducersも変更します。

```reducers/todos.js
const todoReducers = (state = [], action) => {
  switch (action.type) {
    case "ADD_TODO":
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: true,
        },
      ];
    case "TOGGLE_TODO": //追加
      return state.map((todo) =>
        todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
      );
    default:
      return state;
  }
};

export default todoReducers;

```

やっていることとしては、stateに保存されている全てのtodoについて、それぞれのidとActionCreatorに渡された、横線を引きたいtodoのidを比べて、一致したらそのtodoのcompleted属性を逆転させるというものです。

ここで、例の如くApp.jsから動作確認をしてみましょう
App.jsに以下を追加してみましょう。

```App.js
import { addTodo, toggleTodo } from './actions'

store.dispatch(addTodo('Hello React!'))
store.dispatch(toggleTodo(0))
```

画面をみてみると斜線が引かれたtodoが追加されているはずです。

#Todoをクリックしてcompleted属性を操作できるようにする

それでは、画面上からtodoの完了、未完了の操作ができるようにしましょう。mapDispatchToPropsを作成します。
これはcomponentで(今回で言えばTodoListで)dispatchをpropsとして渡せるものです。

こうすることで、component側ではthis.props.onTodoClick(id)の形で先ほどApp.jsでやったdispatch(toggleTodo(0))みたいなことができるようになります。

```containers/VisibleTodoList.js
import { connect } from "react-redux";
import TodoList from "../components/TodoList";
import { toggleTodo } from "../actions"; //追加

const mapStateToProps = (state) => {
  return { todos: state.todoReducers };
};

//追加
const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id));
    },
  };
};

//追加
const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList);
export default VisibleTodoList;
```

これでTodoListの方でonTodoClickが使えるようになったので、追加してみましょう。

```components/TodoList.js
return (
      <View>
        <FlatList
          data={this.props.todos}
          renderItem={({ item }) => (
            <View style={styles.todoList}>
              <Text
                onPress={() => this.props.onTodoClick(item.id)}
                style={{
                  textDecorationLine: item.completed ? "line-through" : "none",
                }}
              >
                {item.text}
              </Text>
            </View>
          )}
          keyExtractor={(item) => item.id.toString()}
        />
      </View>
    );
```

これでtodoをクリックすると該当のtodoに斜線が引かれます。

ToggleTodo編は完成です！
お手元のシミュレーターでお試しください。
ここまでのソースコードは[GitHub](https://github.com/s-amano/todoExample/tree/ToggleTodo)に上げていますのでご参考ください。

次回は表示するTodoをcompleted属性によって切り替える「FilterTodo」機能を実装していきます。

##参考
[Redux ExampleのTodo Listをはじめからていねいに(2)](https://qiita.com/xkumiyu/items/e7e1e8ed6a5d6a6e20dd)