ただ日々を記すもの

意識高めを装うことができます

TODOリストを改修する

前回紹介したTODOアプリを改修していきます。

Image from Gyazo

具体的には以下の2点。

- タスクを追加するごとにテキストボックスの入力値をクリアする
- 管理しやすいようにディレクトリ分けを行う

テキストボックスの入力値をクリアする

タスクを追加したときに、Storeで保持しているtaskに空文字をセットします。

// tasksReducer
    case 'ADD_TASK':
      return {
        ...state,
        task: '', // 追加
        tasks: state.tasks.concat([action.payload.task])
      }

そして空にしたtaskがテキストボックスに反映されるようにしていきます。

// TodoApp
  return (
    <div>
      {/* value={task}を追加 */}
      <input type="text" value={task} onChange={(e) => store.dispatch(inputTask(e.target.value))} />
      <input type="button" value="ADD TASK!" onClick={() => store.dispatch(addTask(task))} />
      <ul>
        {tasks.map((task, index) => {
          return (<li key={index}>{task}</li>)
        })}
      </ul>
    </div>
  )

これでタスクを追加するごとに入力値がクリアされるようになります!

ただ、このままだと何も入力せずに「ADD TASK!」ボタンを押すと空文字がリストに追加されてしまいます。

これを直すために、空文字のときはStoreに追加されないようにしていきます。

// tasksReducer
    case 'ADD_TASK':
      if (!action.payload.task) return state // 追加
      return {
        ...state,
        task: '',
        tasks: state.tasks.concat([action.payload.task])
      }

これで完成です!

Image from Gyazo

ディレクトリ分けを行う

次にディレクトリ分けを行っていきます。
今回は以下のような構成にしていきます。

/components
/actions
/reducers
reducer
// reducers/tasksReducer.js

const initialState = {
  task: '',
  tasks: []
}

export function tasksReducer(state = initialState, action) {
  switch (action.type) {
    case 'INPUT_TASK':
      return {
        ...state,
        task: action.payload.task
      }
    case 'ADD_TASK':
      if (!action.payload.task) return state
      return {
        ...state,
        task: '',
        tasks: state.tasks.concat([action.payload.task])
      }
    default: return state
  }
}
actions
// actions/tasks.js

export const inputTask = (task) => ({
  type: 'INPUT_TASK',
  payload: {
    task: task
  }
})

export const addTask = (task) => ({
  type: 'ADD_TASK',
  payload: {
    task: task
  }
})
components
// components/TodoApp.js

import React from 'react'
import { inputTask, addTask } from '../actions/tasks'

export default function TodoApp({ store }) {
  const { task, tasks } = store.getState()
  return (
    <div>
      <input type="text" value={task} onChange={(e) => store.dispatch(inputTask(e.target.value))} />
      <input type="button" value="ADD TASK!" onClick={() => store.dispatch(addTask(task))} />
      <ul>
        {tasks.map((task, index) => {
          return (<li key={index}>{task}</li>)
        })}
      </ul>
    </div>
  )
}
index.js
import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux'
import TodoApp from './components/TodoApp'
import { tasksReducer } from './reducers/tasksReducer'

const store = createStore(tasksReducer)


function renderApp(store) {
  render(
    <TodoApp store={store} />,
    document.getElementById('root')
  )
}

store.subscribe(() => renderApp(store))
renderApp(store)

これでディレクトリわけも完了です!