Slide 1

Slide 1 text

Introduction to flux-util @joe_re

Slide 2

Slide 2 text

Who am I? twitter: @joe_re github: @joe­re working in freee.K.K

Slide 3

Slide 3 text

2015 年初頭に勃発した 俺が最強のflux 実装だ 戦争

Slide 4

Slide 4 text

名乗りを上げた者たち Alt Reflux Fluxxor Fluxible nuclear­js Arda Material Flux Delorean Flummox Redux etc...

Slide 5

Slide 5 text

多い( こなみ)

Slide 6

Slide 6 text

全世界が疲弊

Slide 7

Slide 7 text

俺たちはいつまでflux framework の比較検証を続 けなければいけないのか

Slide 8

Slide 8 text

そんな中で颯爽と登場 したRedux! (2015 年5 月)

Slide 9

Slide 9 text

Redux の世界をざっくり 全ての状態は1 つのJSON で表す(Single Store) Data Flow の登場人物(Action, Reducer) はただの関数になる state はreducer という関数を通すことで更新する

Slide 10

Slide 10 text

Redux の世界をざっくり

Slide 11

Slide 11 text

既存のアプリケー ションへの導入にはつらいポイント

Slide 12

Slide 12 text

既存のアプリケー ションへの導入にはつらいポイント

Slide 13

Slide 13 text

Single Store を構築 するのが難しい

Slide 14

Slide 14 text

そこに颯爽と登場したFlux Util! (2015 年8 月)

Slide 15

Slide 15 text

Flux Util is 何 flux の発表後、 様々 なflux framework で提示されたベストプ ラクティスをfacebook がいいとこ取りした( 主観) これまで提供していたDispatcher だけでなく Store の各実装とContainer という概念が追加された flux に対する欲望を全て満たすものではない( ミニマムな実 装) https://facebook.github.io/flux/docs/flux­utils.html Flux frameworks out there if these utilities do not fulfill your needs.

Slide 16

Slide 16 text

ここをサポー ト

Slide 17

Slide 17 text

Added Modules 1. Store 2. ReduceStore 3. MapStore 4. Container

Slide 18

Slide 18 text

Stores Store < Reduce Store < Map Store Store はFlux Utils が提供するStore の基底クラス Store を直接使うことはない ReduceStore、MapStore を利用する Store 間の依存関係定義には従来通りwaitFor が使える (Store にwaitFor に渡すためのgetDispatchToken() というメソ ッドが用意されている)

Slide 19

Slide 19 text

Facebook の考えるStore のベストプラクティス 1. Store はキャッシュである 2. public にgetter のみを提供する(setter はない) 3. Dispatcher 経由で受け取った特定のAction に反応する 4. 自身の持つデー タが変わった時は常にchange イベントを発 行する 5. dispatch 中にはchange イベントの発行のみを行う

Slide 20

Slide 20 text

Reduce Store c l a s s C o u n t e r S t o r e e x t e n d s R e d u c e S t o r e { g e t I n i t i a l S t a t e ( ) { r e t u r n 0 ; } / / ① r e d u c e ( s t a t e , a c t i o n ) { s w i t c h ( a c t i o n . t y p e ) { / / ② c a s e C o u n t e r A c t i o n . I N C R E M E N T r e t u r n s t a t e + 1 ; / / ③ d e f a u l t : r e t u r n s t a t e ; } } } ① 初期値の設定 ② Action によって処理を分岐 ③ 変更後の値を返却することで更新を伝える

Slide 21

Slide 21 text

Reduce Store's reduce method reduce 関数はRedux のreducer と考え方は同じ Redux のreducer はSingle Store に更新を伝えるものだけど、 ここで適用されるのは自分自身の状態の変更 ( 既存のflux と乖離がない) reduce 関数で値が変更されると自動でchange イベントが 発行されて、Container( 後述) に変更が通知される flux を生で書くと変更のdispatch、listen のコー ドが 大量に発しがちだけど、 この仕組みがあるとそのあたりのコー ドが消える

Slide 22

Slide 22 text

Thinking about Reduce Store state はImmutable なオブジェクトとして扱うべき 変更がない場合は前回のstate をそのまま返す a r e E q u a l ( o n e : T , t w o : T ) : b o o l e a n メソッドを オー バライドすることで変更判定の挙動は変えられる けどそもそもImmutable なオブジェクトであればそういうこ とをする必要はなくなって、 余計なコー ドを減らせる

Slide 23

Slide 23 text

Map Store c l a s s T o d o S t o r e e x t e n d s M a p S t o r e { r e d u c e ( s t a t e , a c t i o n ) { / / ① s w i t c h ( a c t i o n . t y p e ) { c a s e T o d o A c t i o n . A D D : / / ② r e t u r n s t a t e . s e t ( a c t i o n . i d , { i d : a c t i o n . i d , t e x t : a c t i o n . t e x t / / ③ } ) ; d e f a u l t : r e t u r n s t a t e ; } } } ① Immutable.Map() をState として扱う( デフォルトでImmutable.Map() になる) ② Action によって処理を分岐(ResuceStore と同様) ③ 再生成したImmutable.Map を返却する

Slide 24

Slide 24 text

Thinking about Map Store ReduceStore を継承しているのでreduce が同様に使える state はImmutable.js のMap になる(Immutable.js に依存) なので値がImmutable であることを確実に保証できる Immutable.js のAPI を活かしたAPI が追加される at(key: K): V has(key: K): boolean has(key: K): boolean getAll(keys: Iterable, prev: ?Immutable.Map): Immutable.Map 開発者による書き方のばらつきをある程度抑えられる

Slide 25

Slide 25 text

Immurabe.js のサイズが大きいのがつらい。。 (minify なしで140kb)

Slide 26

Slide 26 text

With Flow Immutable.js は静的型付けとの相性が良いので、 Flow との組み合わせると真価を発揮する。 ( もちろんTypeSctipt もOK) https://facebook.github.io/immutable­js/ https://github.com/facebook/flux/tree/master/examples/flux­ utils­todomvc

Slide 27

Slide 27 text

Container View はContainer とそれ以外とに分けて考える Container は各Component の親となり、Store との通信、 各 Component へのprops の通知を行う

Slide 28

Slide 28 text

Facebook の考えるContainer のベストプラクティス 1. View をcontroll するReact Copmponent である 2. 必要な情報をStore から集め、 それらをstate として保持する 3. props とUI ロジックは持ってはいけない

Slide 29

Slide 29 text

Facebook の考えるView のベストプラクティス 1. 全てのReact Component はConrtainer によって管理される 2. 全てのUI と描画のロジックはここで持つ 3. 全ての情報とcallback はprops として受け取る

Slide 30

Slide 30 text

Container c l a s s C o u n t e r C o n t a i n e r e x t e n d s C o m p o n e n t { s t a t i c g e t S t o r e s ( ) { r e t u r n [ C o u n t e r S t o r e ] ; / / ① } s t a t i c c a l c u l a t e S t a t e ( p r e v S t a t e ) { r e t u r n { c o u n t : C o u n t e r S t o r e . g e t S t a t e ( ) } ; / / ② } r e n d e r ( ) { / / ③ r e t u r n < C o u n t e r U I c o u n t = { t h i s . s t a t e . c o u n t } / > ; } } ① 監視する対象のStore を指定する ② store でchange イベントが発行されると、caculucateState メソッドが呼ばれる   返り値が新しいstate となる( 引数では前回のstate が受け取れる) ③ 更新されたstate をprops としてComponent に渡す( ここではUI は決して持たない!!)

Slide 31

Slide 31 text

Container getStores とcalculateStore メソッドを定義するだけで 特定のstore のchange イベントのlisten が自動で行われる React にもともとあった、 状態を持つComponent は親だけで あるという考え方を洗練し、 明文化した Redux のドキュメントやExample を見ても同様の概念が適用 されている http://redux.js.org/docs/basics/UsageWithReact.html#container­ and­presentational­components https://github.com/reactjs/redux/tree/master/examples/todomvc

Slide 32

Slide 32 text

まとめ flux­util は既存のflux flow を壊さない範囲で、 ベストプラクティスを使いやすくしたもの 所詮新たなStore とReact Component を提供するだけなので 大きくはロックインしない 実装が超ミニマム(Store 各種とContainer 合わせて800 行ぐら いしかない) アプリケー ション全体に関わるmodule はないので部分適用 可能 && 既存のアプリケー ションにも導入しやすい( 体感)