1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ReduxのサンプルのTodoリストを真似てみる。Part.2

Last updated at Posted at 2018-05-28

ReduxのサンプルのTodoリストを真似てみる。Part.1の続きです。

0.留意点

  • Redux ExampleのTodo Listをはじめからていねいに(1)を参考にさせて頂いて、Reduxのコードを書いた。
  • 初心者の覚書です。
  • 自分の環境で動くように参考にしたコードを適当に修正している。
  • Windows10 64bit , PowerShellなどで動かしている。
  • 見栄えを若干よくする為にbootstrap4を利用している。

1.Todoの配列でTodoリストを作る

reducersを修正

todoをtodosに変更 stateをtodoの配列にする
ファイル名を reducers/index.jsからreducers/todos.js に変更

reducers/todos.js
const todos = (state=[], action) => {
    switch (action.type) {
        case 'ADD_TODO':
            return {
                ...state,
                id: action.id,
                text: action.text
            }

        default:
            return state;
    }
}
export default todos;

actions/index.jsはあたらしく作り直す。
combineReducers関数を使って、複数のreducers(複数のロジック)をまとめて扱えるようにする。
たとえば、
reducers/hoge.js のなかで、export default hoge
reducers/fuga.js のなかで、export default fuga
し、actions/index.jsで、importして
combineReducers({todos, hoge, fuga})
としておくと、stateオブジェクトのtodosプロパティ、hogeプロパティ、fugaプロパティとしてアクセスできる。この時点ではtodosだけだが、先のことを考えて準備しておく。

reducers/index.js
import todos from './todo'
import { combineReducers }  from 'redux';

const todoApp = combineReducers({todos});
export default todoApp;

コンポーネントをつくる

この辺から、bootstrapを使う。クラス名の指定でできるだけ対応。React、Reduxは関係しない。

コンポーネントの前にまず、ルートのhtmlファイルを修正

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>React,ReduxでTodoリストを作ろう</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  </head>
  <body >
      <!-- classでBootsrapに関する設定 -->
    <div class="mx-auto w-50 mt-3"  id="root"></div>

    <script src="dist/index.js"></script>
  </body>
</html>

Todo一つ一つに対応するTodoコンポーネント

components\Todo.js
import React from 'react';
import PropTypes from 'prop-types';

//classNameでBootsrapに関する設定
const Todo = ({text})=>(
    <li className="list-group-item">{text}</li>
)

Todo.propTypes ={
    text:PropTypes.string.isRequired
}

export default Todo;

複数のTodoコンポーネントを格納するTodoListコンポーネント

components\TodoList.js
import React from 'react';
import PropTypes from 'prop-types';
import Todo from './Todo';

//classNameでBootsrapに関する設定
const TodoList = ({todos})=>(
    <ul className="list-group mx-auto p-3 bg-info rounded" style={{maxWidth:'36rem'}}>
    {todos.map(
        (todo)=>(<Todo key={todo.id} {...todo} />)
    )}
    </ul>
)

TodoList.propTypes = {
    todos: PropTypes.arrayOf(PropTypes.shape({
      id: PropTypes.number.isRequired,
      text: PropTypes.string.isRequired
    }).isRequired).isRequired
  }
  
export default TodoList

コンテナでstateとコンポーネントを結びつける

VisibleTodoListコンテナのなかで、state.todosを TodoListのpropsに関連付ける。
そのために、React-Reduxのconnect関数を使う。

containers\VisibleTodoList.js
import React from 'react';
import { connect } from 'react-redux';
import TodoList from '../components/TodoList'


function mapStateToProps(state){
    return {
        todos:state.todos
    }
}

const VisibleTodoList = connect(mapStateToProps)(TodoList);
export default VisibleTodoList;

Appコンポーネントを修正

Appコンポーネントでは、上記のVisibleTodoListコンテナを読み込む。

components\App.js
import React from 'react';
import VisibleTodoList from '../containers/VisibleTodoList'

//classNameでBootsrapに関する設定
const App = () => (
    <div>
    <h1 className="text-center alert alert-info ">Todoリスト</h1>
        <VisibleTodoList />
    </div>
)

export default App;

エントリーポイントのindex.jsを修正

ここまでの変更に合わせて、import関係、モジュール参照名などを修正。

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import todoApp from './reducers'
import { createStore } from 'redux';
import App from './components/App'
import addTodo from './actions'

let store = createStore(todoApp);
store.dispatch(addTodo('Todo 1番目'));
store.dispatch(addTodo('Todo 2番目'));
store.dispatch(addTodo('Todo 3番目'));
store.dispatch(addTodo('Todo 4番目'));
store.dispatch(addTodo('Todo 5番目'));


ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
);

コマンド実行
npm run build
npm run start

http://localhost:8080で動作確認

2018_0528_1351_34.jpg

ソースコード 03

2.Todoの新規追加のフォームをつくる

初めの読み込み時に、input変数にDOMへの参照が格納される。
AddTodo コンポーネントにdispatchを引数で渡す。
新規追加ボタンをクリックすると、コールバックで、ユーザー入力のテキストを用いたactionを引数にしてdispatch関数を実行。

containers\AddTodo.js
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import addTodo from '../actions/index.js';

let AddTodo = ({ dispatch }) => {
    let input;
    //className,htmlForなどはbootstrapのため
    return (
        <div className="form-group">
            <label htmlFor="todo_name">Todoの名称</label>
            <input type="text" className="form-control" id="todo_name" placeholder="Todoの名称" ref={(node) => { input = node }} />
            <button className="btn btn-primary btn-lg btn-block mt-1" onClick={() => { dispatch(addTodo(input.value)); input.value="" }}>新規追加</button>
        </div>
    )
}
AddTodo = connect()(AddTodo);
export default AddTodo;

Appコンポーネントを修正

components\App.js
import React from 'react';
import VisibleTodoList from '../containers/VisibleTodoList'
import AddTodo from '../containers/AddTodo'

//classNameでBootsrapに関する設定
const App = () => (
    <div>
    <h1 className="text-center alert alert-info ">Todoリスト</h1>
        <VisibleTodoList />
        <AddTodo />
    </div>
)

export default App;

実行結果

2018_0528_1531_46.jpg

ソースコード 04

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?