React を導入したフロントエンド開発

69
React ををををを ををををををををを をををををををををををを をををををををををををををををををを2015.12 GMO ををををををを をををををををををを をを をを

Transcript of React を導入したフロントエンド開発

React を導入したフロントエンド開発

~フレームワークを利用した

シングルページアプリケーションの制御~

2015.12GMO インターネット次世代システム研究室

松井 大介

管理画面のフロントエンドにReact を導入したっていう話です。

アジェンダ

• 絶対王者 Angular vs 挑戦者 React• React での SPA 設計 1.コンポーネントを分ける 2. ReactRouter 3. jQuery との共存

アジェンダ

• 絶対王者 Angular vs 挑戦者 React• React での SPA 設計 1.コンポーネントを分ける 2. ReactRouter 3. jQuery との共存

GMO スマートリザーブのご紹介

飲食店向け予約一元管理

2015 年 4 月 -8 月次世代システムがサービス立ち上げを支援しました

【日本】マネージャー 1 名ベトナムブリッジ 1名【ベトナム】ベトナム 3 名

デモ

フロントエンド実装期間 1 ヶ月弱

システムの特徴

• バックエンド データ操作用 API サーバを用意。 (外部連携を意図)

• 管理画面= フロントエンドだけ 1. JS による SPA から API を叩く。 2. 管理画面なので そこまで厳しいパフォーマンス要件はない

SPAシングルページアプリケーション

1. HTML のレンダリングを全てクライアントサイドでやる!

2.サーバにアクセスするのは API でデータ取得・保存するときだけ!

SPAシングルページアプリケーション

1. HTML のレンダリングを全てクライアントサイドでやる!

2.サーバにアクセスするのは API でデータ取得・保存するときだけ!

ここぞとばかりに新しいJS フレームワーク使いたい!!!

JS フレームワーク戦国時代

Google トレンド

https://www.google.co.jp/trends/explore#q=angular%20js%2C%20backbone%20js%2C%20react%20js&cmpt=q&tz=Etc%2FGMT-9

絶対王者 Angular• Google が開発

• 高機能フロントエンド MVC 全部盛り双方向データバインディングヴァリデーションとか全自動機能多い

• HTML 拡張デザイナーでも見やすい

React が注目された理由

• Facebook / Instagram で開発 + 利用

• 双方向データバインディングに対する懐疑 (高機能すぎて複雑、処理が重い)

React の斬新なコンセプト

• VirtualDOM 1.実装者は仮想の DOM を記述 2. React は変更発生した場合仮想 DOM の 差分を確認し、リアル DOM を更新 ⇒ 軽量な描画コスト

• 一方向なデータフロー かならず同じ順序で処理される。 状態が変わるたびに再描画される。 ⇒ 保守しやすい

React でできること

• 画面描画処理の統一化 React のライフサイクルに合わせて描画

• 画面パーツのコンポーネント化 共通のパーツ整理

描画パフォーマンス

https://www.codementor.io/reactjs/tutorial/reactjs-vs-angular-js-performance-comparison-knockout

比較項目 Angular React

機能 高機能管理画面構築は非常に楽。

実装が必要

デザイナー親和性 高基本 HTML

低JSX+ カスタムタグは読みづらい

パフォーマンス 低 高将来性 1 系 × (打ち切

り)2 系??

枯れてない。どんどん変わる。

好み もりもりすぎなんじゃないの?

一方向なデータフローが読みやすい!

学習の平易さを優先しReact 採用しました★

React での SPA 設計

アジェンダ

• 絶対王者 Angular vs 挑戦者 React• React での SPA 設計 1.コンポーネントを分ける 2. ReactRouter 3. jQuery との共存

画面パーツをReact コンポーネント化

React での設計ポイント

• 画面パーツをコンポーネントにする。• 親コンポーネント子コンポーネントで 値の受け渡し+イベントを整理する。

DaySelectコンポーネント

TableScheduleコンポーネント

ReservationFooter コンポーネント

Modalコンポーネント

ReserveFormコンポーネント

var HomeScreen = React.createClass(){

render : function() {return <div> <DaySelect/> <TableSchedule/> <ReservationFooter/>

<Modal> <ReserveForm/> </Modal></div>})..};

JSX +コンポーネントタグ= JS 内の render() 中にHTML と独自タグを記述

var DaySelect = React.createClass(){ // 初期化 getInitialState(){...}, // 描画前 componentWillMount() {...}, // 描画 render() {...}, // 描画後 componentDidMount() {...}, // クリックイベント onClickBotton() {...}}

http://qiita.com/kawachi/items/092bfc281f88e3a6e456

http://qiita.com/kawachi/items/092bfc281f88e3a6e456

ライフサイクルさえ把握すればReact を制したも同然

TableScheduleコンポーネント

予約時間をクリック

var HomeScreen = React.createClass(){

render : function() {return <div> <DaySelect/> <TableSchedule onClickReservation={this.onClickReservation}/> <ReservationFooter/>

<Modal> <ReserveForm/></Modal>

var HomeScreen = React.createClass({onClickReservation: function(reservation) { this.setState({ inputReservation: reservation, isModalOpen: true, doneButtonName:‘ 予約修正’ , cancelButtonName:' 予約取消 ' }); }, setState() ⇒ 再描画

ReserveFormコンポーネント修正ボタンクリック

var HomeScreen = React.createClass(){

render : function() {return <div> <DaySelect/> <TableSchedule onClickReservation={this.onClickReservation}/> <ReservationFooter/>

<Modal> <ReserveForm onDone={this.updateReservation}/></Modal></div>})..};

updateReservation: function(reservation) {

request.post(apiHost + ‘/shops/’ + this.props.shopId + ‘/reservations’) .query({token:accessToken}) .send(query) .end(function (err, res) { // 保存完了したら戻る処理 };

};※request オブジェクトは superagent.js をラップ

React コンポーネント理解のポイント

• ライフサイクルメソッドで生成される!• setState() で再描画される!

React Router

React Router• ルーティングライブラリ• URL と React コンポーネントの対応定義• ヘッダー、サイドバー、フッターの共通化

SPA=1 画面制御

ログイン画面 ホーム画面 週間スケジュール画面

すべて app.js から Routing される

ログイン画面login_screen

予約ページフッターreservation_footer

週間スケジュールweek_schedule

ホーム画面home_screen

メニューヘッダーmenu_header

メニューヘッダーmenu_header

予約ページフッターreservation_footer

すべて app.js から Routing される

<Route name="app" path="/" handler={App}>

<Route name="home" path="/shops/:shopId“ handler={HomeScreen}/>

<Route name="weekSchedule“ path="/shops/:shopId/week_schedule“ handler={WeekScheduleScreen}/>

<Route name="login" path="/" handler={LoginScreen}/>

<DefaultRoute handler={LoginScreen}/> </Route>

一元管理

jQuery との共存

jQuery UI Datepicker

jQuery UI Datepicker普通に使うと動かない!

jQuery 初期化は画面描画時

<script>   // 画面描画後に呼ばれる jQuery の処理    $(document).ready(function(){        // datepckr に機能をバインドする        $("#datepckr").datepicker();    });</script><input type="text" id="datepckr" />

React は setState で何度も再描画

getInitialState : 初期化時に 1回だけ

componentWillMount : render 前処理render : 描画処理componentDidMount : render 後処理componentWillUpdate : State 変更後 render の前componentDidUpdate : State 変更後componentWillUnmount :コンポーネント削除前

=クリックイベント処理のバインドが外れてしまう

http://qiita.com/kawachi/items/092bfc281f88e3a6e456

render 直後であれば DOM 操作可能

getInitialState : 初期化時に 1回だけ

componentWillMount : render 前処理render : 描画処理componentDidMount : render 後処理componentWillUpdate : State 変更後 render の前componentDidUpdate : State 変更後componentWillUnmount :コンポーネント削除前

componentDidMount: function () {             self = this;             $('.input-date').datepicker(                    {                        //Datepicker 初期化のための値                        dateFormat: 'yy-mm-dd',                        //選択時のイベント処理                        onSelect: function(dateVal) {                           // 親コンポーネントに変数渡すなどの処理

                        }                    }                );              }

jQuery が data-reactid をいじってしまうと破壊されるので注意

<section data-reactid=".0.1.0.1"><div data-reactid=".0.1.0.1.0"><dl data-reactid=".0.1.0.1.0.0"><dt data-reactid=".0.1.0.1.0.0.0">

他にがんばったところCanvas in React

やらなかったこと

• サーバサイドレンダリング主に SPA の SEO 対策用処置。管理画面なので SEO関係なかった。

• Flux開発期間の都合であきらめた。今後改善できる部分。

まとめ

• Angular もいいけど React が平易そう• React での SPA 設計 1.コンポーネント化が基本 2. ReactRouter で統一的に画面遷移制御 3. jQuery との共存の方法は ライフサイクルを把握する

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

アジェンダ

• 絶対王者 Angular vs 挑戦者 React• React での SPA 設計 1.コンポーネントを分ける 2. ReactRouter 3. jQuery との共存• もうちょっとがんばれば Flux

改善できそうなところ

改善できるところ

• もっと Flux をやるなら

良く見る Flux の図

公式にある Flux の図(実はシンプル)

• View = React でつくった画面。onClick などイベントがあれば Action を呼ぶ。

• ActiononClick などのイベント処理の集約クラス。イベントが発生したら Dispatcher を呼ぶ。渡すデータのことをペイロードと呼ぶ。

• DispatcherAction からデータ(ペイロード)をもらって Store を操作するクラス。

• StoreAjax や Localstorage などデータ取得・保存系の処理を行うクラス。

結局 Flux とは

一方向 MVC

• Model ≒ Store• View = View• Controller ≒ Action + Dispatcher

※厳密には違うが、理解の取っ掛かりに

流れは一方向

Flux に変更する上で必要なことたとえば HomeScreen コンポーネントなら

画面描画系 ⇒ React コンポーネント            (いままで通り) 

イベント系 onClickReservation ⇒ Action クラスへ

保存イベント系onSave ⇒ Action + Dispatcher クラスへ

保存処理request.post (ajax) ⇒ Store クラスへ