前回紹介したTODOアプリを改修していきます。
具体的には以下の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]) }
これで完成です!
ディレクトリ分けを行う
次にディレクトリ分けを行っていきます。
今回は以下のような構成にしていきます。
/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)
これでディレクトリわけも完了です!