React.js + Reduxで作る
SPA
@saekis
@saekis
• 91年生まれ(25歳)
• Software engineer
SPAとは
“A single-page application (SPA) is a web application
that fits on a single web page providing a
more fluid user experience
similar to a desktop application”
出典: Wikipedia
従来のweb
• ページ遷移の度にサーバへHTTPリクエスト
• その度にHTMLやassetsファイルをダウンロー
ド、そしてDOMの生成
• 必要に応じてajaxを使う
• 遅い
SPA
• ページ遷移の度にブラウザをリロードさせず、コンテンツとな
るDOMの更新のみ行う
• HTMLやassetsファイルのダウンロードは初回リクエスト時のみ
• 必要なデータをajaxで取得
• 速い
• ネイティブアプリ
React.js
リリースから3年
みなさん、React
書いてますか?
MVC
React.jsとは
• Facebook製
• UI描画のためのライブラリ
• Component -> VirtualDOM -> DOM
VirtualDOM??
VirtualDOM??
VirtualDOM Tree VirtualDOM Tree
DOM Tree
差分を計算
反映
VirtualDOM??
VirtualDOM Tree VirtualDOM Tree
差分を計算
反映
<div>hoge</div>
<div>foo</div>
<div>hoge</div>
<div>piyo</div>
<div>hoge</div>
<div>piyo</div>
VirtualDOM??
• 仮想DOMとして現在のDOMの状態を記憶
• レンダー前の仮想DOMと現在の仮想DOMの差
分を計算
• 差分のみDOMに反映
JSX
JSX
• HTMLタグっぽい何か
• JSのコードにHTMLっぽい定義をするための
言語
JSX
import React from 'react'
export default class CommentBox extends React.Component {
render() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
)
}
}
JSX
import React from 'react'
export default class CommentBox extends React.Component {
render() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
)
}
}
JSX
import React from 'react'
export default class CommentBox extends React.Component {
render() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
)
}
}
var div = document.createElement("div");
div.className = 'commentBox';
div.innerHTML = "Hello, world! I am a CommentBox.";
変換
JSX
• ブラウザにJSとして解釈させるためにはコンパイルが必要
• JSX -> browserify, babelify -> JS
• browzerifyはブラウザ上でもNode.jsのモジュールを使える
ようにするために使う
• babelifyはES6->ES5の変換、JSX->JSの変換をするために
使う
JSX -> JS
import gulp from 'gulp'
import browserify from 'browserify'
import babelify from 'babelify'
import source from 'vinyl-source-stream'
import duration from 'gulp-duration'
gulp.task('browserify', () => {
return browserify({entries: [“./react/app.js“]})
.transform(babelify, {presets: ["es2015", "react"], plugins: ["babel-plugin-transform-object-
assign"]})
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest(config.dest + '/react'))
.pipe(duration('browserify'))
})
Redux
Redux
• Fluxアーキテクチャに基づいて設計された
Javascriptフレームワーク
• FacebookもFluxフレームワークの中では
Reduxを使うことを推奨している(たぶん)
Flux?
Flux?
Flux?
• アーキテクチャ(設計思想)
• データは必ず一方向にしか流れないように設
計される
• Action -> Dispatcher -> Store -> View ->
Action -> …
Redux
• Fluxアーキテクチャに基づいて設計された
Javascriptフレームワーク
Redux
React + Reduxで
SPAをつくる
SPAをつくる
• Reactコンポーネント
• route定義
• reducer
• Redux state -> React prop
route定義
import { Provider } from 'react-redux'
import { Router, Route, IndexRoute, browserHistory } from 'react-router'
<Provider store={store}>
<Router history={history}>
<Route path="/hoge" component={Index} >
<Route path="foo" component={FooContainer}></Route>
<Route path="piyo" component={PiyoContainer} ></Route>
</Route>
</Router>
</Provider>
react-redux
• Reduxの”state”とReactの”prop”をつなぐ
• 明示的に書かなくても、stateの更新を
componentがsubscribeしてくれる
react-redux
import { connect } from ‘react-redux'
import hogeComponent from '../components/hoge'
function mapStateToProps(state) {
return { user: state.user }
}
function mapDispatchToProps(dispatch) {
return {
hoge: () => { dispatch(hoge()) },
foo: () => { dispatch(foo()) }
}
}
export default connect(mapStateToProps, mapDispatchToProps)(hogeComponent)
実務で使ってみた感想
実務で使ってみた感想
• テストがしやすい
• Reduxのコード量がとにかく多くなる感じ
• 特にaction createrの肥大化
ご清聴ありがとう
ございました

React.js + Reduxで作るSPA