Edited at

React + Redux + TypeScriptとImmutable.js

More than 3 years have passed since last update.

こちらの記事の続編です。

http://qiita.com/uryyyyyyy/items/30733e9cd140e60c52bd


問題提起

今時、型のない言語とか使いたくないですよね!(JSerにケンカ売る挨拶)

今回はtodoListのサンプルを通じて、immutableJSの良さを再確認しましょう。


環境


  • NodeJS 5.x~

  • React 15.1

  • TypeScript 1.8


構成

こちらをご参照ください。

https://github.com/uryyyyyyy/react-redux-sample/tree/immutable


Immutable.jsとは

JSでListやMapなどのコレクションを扱えるもの。

TypeScriptで使うと、ネイティブのArrayやObjectと比べて使えるメソッドが増えるのでオススメです。

(逆にJSで使うのであれば、ネイティブの型と混同しがちなのでlodashとかの方が良いのではないでしょうか?)

npm install immutable --save

typings install dt~immutable --global --save


ネイティブ型の場合

let list:number[] = [1, 2]

//そんなものはない。
list.isEmpty()

list.push(3)
list // [1,2,3] 破壊的メソッドコワイ


Immutable.jsのList型の場合

import {List} from "immutable";

let list:List<number> = List.of<number>(1, 2)

//ある!
list.isEmpty()

let newList = list.push(3)
list // [1,2] Immutable!


Immutable.jsでTodoList

https://github.com/uryyyyyyy/react-redux-sample/tree/immutablejs

基本コードを見てもらったほうが早いように思いますが、要点だけ。


src/todo/Reducer.ts


const initialState:TodoState = {todos: List.of<Todo>(), marks: marks};

export function todoReduce(state: TodoState = initialState, action: MyAction): TodoState {

function changeStatus(state: TodoState, action: MyAction):TodoState {
const newTodos = state.todos.map(v => {
if (v.id === action.id) return new Todo(v.id, v.text, !v.isComplete);
return v
});
return objectAssign({}, state, {todos: newTodos});
}

function addTodo(state: TodoState, action: MyAction):TodoState {
let newNumber = 1;
if(!state.todos.isEmpty()) newNumber = state.todos.map(v => v.id).max() + 1;
const newTodo = new Todo(newNumber, action.text, false);
return objectAssign({}, state, {todos: state.todos.push(newTodo)});
}

function deleteTodo(state:TodoState, action:MyAction):TodoState {
return objectAssign({}, state, {todos: state.todos.filter(item => item.id !== action.id)});
}
}



src/todo/TodoItem.tsx

export interface Props {

/* ... */
marks: Map<boolean, string>
}

render () {
return (
<li>
<span>{this.props.marks.get(this.props.item.isComplete)}: {this.props.item.text} </span>
/* ... */
);
}


どうですか。Immutable.Listのおかげで綺麗に書けてる気がしませんか?

(うーん。。この例だと言うほど便利じゃなさそうかも?まぁ、SetやStackなど色々な便利コレクションが同梱されているので、それ系に慣れている方だとかなり便利かと思います。)

注意点としては、jsonサーバーとの通信で来るjsonは勝手にImmutable.jsのオブジェクトにならないので、都度変換する必要があります。

  const json: TodoInterface[] = [

{id: 1, text: "todo 1", isComplete: true},
{id: 2, text: "todo 2", isComplete: false}
];
const todos: List<TodoInterface> = List.of(...json);

逆にimmutable.jsオブジェクトからjsonへの変換は期待通りになります。

https://facebook.github.io/immutable-js/#converts-back-to-raw-javascript-objects-