Slide 1

Slide 1 text

Should I use redux-saga or not? @kuy / Yuki Kodama 2016.09.27 @ React.js meetup #4

Slide 2

Slide 2 text

自己紹介 @kuy (カイ) / Yuki Kodama 株式会社ジャパンベンチャーリサーチ entrepedia(アントレペディア)の開発・運用 AWS, Ruby on Rails, JavaScript (React + Redux) ● redux-sagaで非同期処理と戦う ● Reduxでコンポーネントを再利用する ● Reduxのmiddlewareを積極的に使っていく ● ・・・など Qiita の記事 発表 ● なぜReduxを使うのか

Slide 3

Slide 3 text

✨ redux-saga ✨

Slide 4

Slide 4 text

← ナルトの人 ✨ redux-saga ✨ Yassine Elouafi 氏 github: @yelouafi twitter: @YassineElouafi2

Slide 5

Slide 5 text

redux-saga というのは ● Redux の Middleware ● React にも Redux にも書きたくないコードを置く場所を提供 ● generator/yield によって非同期処理を同期処理として書ける ● あらゆる副作用をデータとして扱える ○ 強制されるわけではない ● ギリギリまでモックを使わないテストが可能 ○ モック不要とは言ってない サンプルあるよ! https://github.com/kuy/redux-saga-examples

Slide 6

Slide 6 text

redux-saga 登場人物 Effect を使って処理を書く ● Saga: 実行したい処理をまとめたプロセ スのようなもの ● Effect: データとしての副作用 ● Saga Runtime: 実行環境 ● Effect を yield で返す Generator 関数 ● Saga Runtime が Effect を実行 ● 内部的には状態マシンになってる ● call: (非)同期関数呼び出し ● select: 状態の取得する ● put: Actionのdispatch ● take: Actionを待ち受ける ● fork: 別の Saga を起動する ● cancel: 起動した Saga を中止する ● ....などなど redux-saga が提供する実行環境で Saga を起動する 実装

Slide 7

Slide 7 text

redux-saga の動作イメージ

Slide 8

Slide 8 text

redux-saga の挙動( call ) var eff = mySaga.next(); var ret = yield call(hoge, 10); [1] ... = mySaga.next() [2] ... = yield call(hoge, 10) [3] var eff = ... hoge(10).then(ret => ...) mySaga.next(ret) [4] var ret = ... Saga Runtime Your Saga e.g. (pseudo) “call” effect object { fn: hoge, args: [10] }

Slide 9

Slide 9 text

redux-saga の挙動( select ) var eff = mySaga.next(); var data = yield select(foo); [1] ... = mySaga.next() [2] ... = yield select(foo) [3] var eff = ... var data = foo(getState()) mySaga.next(data) [4] var data = ... Saga Runtime Your Saga e.g. (pseudo) “select” effect object { fn: foo }

Slide 10

Slide 10 text

redux-saga と redux-thunk のコード比較 ----- redux-saga ----- ----- redux-thunk ----- 呼び出しコード(共通) dispatch(fetchAPI());

Slide 11

Slide 11 text

redux-saga のコードが増えてきたら ● 適切に分割する ○ 単一責務を意識する ○ 例:あるActionを受け取ったら別のActionをdispatchして画面遷移する →ActionをチェインさせるsagaとActionを受け取ったら画面遷移するsagaを独 立して動作させる ● 共通のsagaを切り出す ● 変化の少ないソリッドな処理はMiddlewareで書く ○ Socket.IO、Firebaseの連携など ● あくまでもsagaはロジックを書く場所にしておく ● 他で書けない/書きたくないものをsagaで書く ● ・・・詳しく知りたい部分があったら直接聞いて下さい! → @kuy or リアル

Slide 12

Slide 12 text

redux-saga の問題点 ● 基本的に初見殺し ● 学習・導入コストが小さくない ● generator/yield が必須 ○ regeneratorRuntime によってスタックトレースが死ぬ ● 隠しきれないコード中の yield の存在感 ● dispatch された Action を reject できない 他の Middleware はどうなんだろう?

Slide 13

Slide 13 text

redux-saga redux-loop redux-machine redux-api-middleware redux-observable redux-thunk redux-promise redux-effects redux-task redux-logic Side Effect 関連の Middleware 多すぎ・・・ 全部見たい人→ https://github.com/markerikson/redux-ecosystem-links/blob/master/side-effects.md

Slide 14

Slide 14 text

Redux Middleware 戦争最前線!! @kuy / Yuki Kodama 2016.09.27 @ React.js meetup #4

Slide 15

Slide 15 text

Middleware の選び方(テストの容易さ) ※ 個人の感想です

Slide 16

Slide 16 text

Middleware の選び方(プロジェクトの規模) ※ 個人の感想です

Slide 17

Slide 17 text

Middleware の選び方(プロジェクトの規模) ※ 個人の感想です !?

Slide 18

Slide 18 text

Side Effect Middleware に求めているもの ● Scalability + Composability ○ 適切にコードを分割できる、共通化しやすい ○ 全体を知らなくても、部分的な理解でメンテ可能 ● Testability ○ 本当にテストしたい部分だけテストコードを書ける ● Background/Long-Running Process ○ UIコードと完全分離したい

Slide 19

Slide 19 text

redux-thunk redux-saga ⚔

Slide 20

Slide 20 text

Beyond redux-saga…?

Slide 21

Slide 21 text

⚙ redux-logic ⚙

Slide 22

Slide 22 text

redux-logic(まだ実戦投入してない ) ✅ 第一印象:Middleware を構造化してくれる Middleware、内部はRxJS ✅ 副作用コードを validate, transform, process の3つに分ける redux-sagaで不可能だったActionの reject が可能! ✅ 好みの方法でロジックを書ける vanilla, RxJS, async/await 処理によって得意分野が違うから、書き分けするのもあり? ✅ サービスがDIされるので比較的テストしやすい(はず) けど、モックは避けられない・・・? ❌ 副作用をデータとして扱っているわけではない 要調査: async/awaitを使った場合のテストは? "I wrote the rxjs code so you won't have to." by @jeffbski

Slide 23

Slide 23 text

さらに続く期待の新人たち・・・ ● clarus/redux-ship (redux-sagaの正統進化系になりえる?) ○ Composable, typable and testable Redux middleware ● exponentjs/redux-effex ○ Spin off async functions to perform side effects どちらも副作用をデータとして扱っている

Slide 24

Slide 24 text

まとまらない Middleware 戦争、収束の見込み無し。 本当に必要なものを見極めて使っていこうね。

Slide 25

Slide 25 text

yield call(say, “Thank you!”);

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

参考資料 [GitHub] “Redux Ecosystem Links > Side Effects” markerikson/redux-ecosystem-links

Slide 28

Slide 28 text

redux-thunk redux-saga ⚔

Slide 29

Slide 29 text

redux-thunk v.s. redux-saga ● 導入、学習コスト:小さい、大きい ● スケール:しない、する ○ ここで言うスケールってのは機能追加するときに、できるだけ既 存のコードをいじらずに拡張していけるという意味です ● テスト:面倒、簡単

Slide 30

Slide 30 text

学習コスト ● redux-thunkはAction CreatorからActionの代わりに関数投げれば いいだけなので簡単 ● redux-sagaは考え方を学んだ上でGenerator関数の知識も必要 だったりしてサクサク書くまでには慣れが必要

Slide 31

Slide 31 text

導入コスト ● redux-thunkはMiddlewareとして追加して、Action Creatorに処理 を書けば終わり ● redux-sagaはGenerator関数が必須なのでビルド設定の変更が必 要なのと、以前と比べるとcreateStore周りの書き方が若干面倒に なった

Slide 32

Slide 32 text

スケール ● redux-thunkはAction Creatorの中に処理を書くため、が切り出しの 単位になるが、基本的にただの関数なので処理を分割しにくい。共 通化するとしたらAction Creator単位。 ● redux-sagaはそれぞれのsagaがプロセスのように動いてくれるの で他のsagaが何やってるのか気にならないし、責務ごとに分割しや すい。共通化はあらゆるレベルで可能。

Slide 33

Slide 33 text

React.js React.js View State Side Effect

Slide 34

Slide 34 text

React.js + Redux React.js Redux View State Side Effect 状態管理を Redux に任せた

Slide 35

Slide 35 text

React.js + Redux React.js Redux View State Side Effect これどうしよう?

Slide 36

Slide 36 text

React.js + Redux + redux-saga React.js Redux View State Side Effect redux-saga Middleware 理想的な Side Effect Middleware とは?

Slide 37

Slide 37 text

redux-observable ● Netflixが開発、RxJS 5.x ● Epicの導入によってアクの強さが軽減された ● 副作用をデータとして扱ってない ○ → テストのしやすさの観点ではイマイチ ● RxJS知らないのにわざわざ勉強してまで使うメリットは感じられなかった ● RxJSをすでに知っているか、RxJSが大活躍するロジックをたくさん書く なら選択肢に含める、くらいの感じ

Slide 38

Slide 38 text

redux-saga 以外の選択肢 ● redux-thunk ● redux-promise ● redux-observable ● redux-loop ● ...etc @shuheikagawa https://speakerdeck.com/shuhei/redux-middleware-wars-japanese

Slide 39

Slide 39 text

Middlewareの配置からざっくりつかむ ● 後置 → 基本的に監視+追加のAction(安全) ● 前置 → Actionの改変の可能性(注意) ● Store Enhancer → 何するかわからん(要注意)