react.js + reduxで作るspa
TRANSCRIPT
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っぽい定義をするための言語
JSXimport React from 'react'
export default class CommentBox extends React.Component { render() { return ( <div className="commentBox"> Hello, world! I am a CommentBox. </div> ) }}
JSXimport React from 'react'
export default class CommentBox extends React.Component { render() { return ( <div className="commentBox"> Hello, world! I am a CommentBox. </div> ) }}
JSXimport 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 -> JSimport 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-reduximport { 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の肥大化
ご清聴ありがとうございました