React.js + Reduxで作るSPA

Post on 16-Apr-2017

708 views 2 download

Transcript of React.js + Reduxで作るSPA

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の肥大化

ご清聴ありがとうございました