React.js + Immutable.jsによるサンプルソース


React.jsとImmutable.jsを使ったTODOアプリのサンプルソースの紹介です。

🍄 package.jsonの準備とライブラリ導入

React.js、Redux、Immutable.jsを使ってTODOアプリケーションを作る手順を紹介します。

mkdir todo && cd todo

yarn init

# メインのライブラリ
yarn add react react-dom redux react-redux immutable

# 開発用のライブラリ
yarn add --dev webpack babel-loader babel-preset-es2015 babel-preset-react

package.jsonにwebpack用の設定を追記します。

"script": {
"build": "webpack --debug"
}

🎉 webpack.config.js

webpack.config.jsにwebpackのconfigを準備します。

module.exports = {
entry: './src/app.js',
output: {
path: __dirname,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: { presets: [ 'es2015', 'react' ] },
}
]
},
resolveLoader: {
moduleExtensions: ['-loader']
}
};

🍣 index.html

プロジェクト直下に確認用のindex.htmlを作成します。


<html>
<head>
<link rel="stylesheet" href="style.css">
<title>Immutable Todotitle>
head>
<body>
<div id="app">div>
<script src="bundle.js">script>
body>
html>

😼 app.js

エントリポイントの./src/app.jsProviderによってstoreを認識させます。

import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux'
import { Provider } from 'react-redux';
import reducer from './reducer';
import { TodoList } from './containers';

const store = createStore(reducer);

render(


</Provider>,
document.getElementById('app')
);

😸 actions.js

アクションを管理する./src/actions.jsを作成します。

// succinct hack for generating passable unique ids
const uid = () => Math.random().toString(34).slice(2);

export function addTodo(text) {
return {
type: 'ADD_TODO',
payload: {
id: uid(),
isDone: false,
text: text
}
};
}

export function toggleTodo(id) {
return {
type: 'TOGGLE_TODO',
payload: id
}
}

🗻 reducer.js

アクションと現在のstateから新しいstateを生成する./src/reducer.jsを作成します。

import { List, Map } from 'immutable';

const init = List([]);

export default function(todos=init, action) {
switch(action.type) {
case 'ADD_TODO':
return todos.push(Map(action.payload));
case 'TOGGLE_TODO':
return todos.map(t => {
if(t.get('id') === action.payload) {
return t.update('isDone', isDone => !isDone);
} else {
return t;
}
});
default:
return todos;
}
}

🚌 components.js

実際のコンポーネントを./src/components.jsに作成します。コンポーネントにはTodoListTodoが存在します。

import React from 'react';

export function Todo(props) {
const { todo } = props;
if(todo.isDone) {
return <del>{todo.text}del>;
} else {
return <span>{todo.text}span>;
}
}

export function TodoList(props) {
const { todos, toggleTodo, addTodo } = props;

const onSubmit = (event) => {
const input = event.target;
const text = input.value;
const isEnterKey = (event.which == 13);
const isLongEnough = text.length > 0;

if(isEnterKey && isLongEnough) {
input.value = '';
addTodo(text);
}
};

const toggleClick = id => event => toggleTodo(id);

return (
'todo'
>
'text'
className='todo__entry'
placeholder='Add todo'
onKeyDown={onSubmit} />
    'todo__list'
>
{todos.map(t => (
  • 'id'
  • )}
    className='todo__item'
    onClick={toggleClick(t.get('id'))}>

    </li>
    ))}
    l>
    </div>
    );
    }

    🐝 container.js

    コンポーネントがstoreを認識するために、コンポーネントをラップするコンテナ./src/container.jsを作成します。

    import { connect } from 'react-redux';
    import * as components from './components';
    import { addTodo, toggleTodo } from './actions';

    export const TodoList = connect(
    // と同義
    function mapStateToProps(state) {
    return { todos: state };
    },
    // 以下と同義
    //
    // addTodo={text => dispatch(addTodo(text))}
    // toggleTodo={id => dispatch(toggleTodo(id))} />
    function mapDispatchToProps(dispatch) {
    return {
    addTodo: text => dispatch(addTodo(text)),
    toggleTodo: id => dispatch(toggleTodo(id))
    };
    }
    )(components.TodoList);

    🐞 参考リンク

    🖥 VULTRおすすめ

    VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。 最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!

    📚 おすすめの書籍