Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
React Nativeで作ったアプリでRedux-Sagaを使ったので,その話 / TOM ...
Search
pochi
September 01, 2017
Programming
2.2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React Nativeで作ったアプリでRedux-Sagaを使ったので,その話 / TOM Internal Developer Session #7
Redux-Sagaの説明周り
pochi
September 01, 2017
More Decks by pochi
See All by pochi
Expoで開発してアプリを公開して得られた知見 / RNM6
pchw
3
1.9k
Firebaseでラクラクリアルタイムアプリ
pchw
0
1.5k
MongoDB族のための組み込み軽量DB NeDB
pchw
0
1.5k
月刊ライトニングトーク2014年8月号: MEAN 祭り資料
pchw
0
4.3k
Synth - 東京Node学園2014
pchw
0
4.5k
RubyMotion 1.15で追加されたtest周りの話
pchw
1
3.2k
Other Decks in Programming
See All in Programming
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
150
属人化した知識を、 AIが辿れる地図にする
pkshadeck
PRO
1
140
2年かけて Deno に DOMMatrix を実装した話 / How I implemented DOMMatrix in Deno over two years
petamoriken
0
200
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
180
Lean は証明の正しさを確認するためだけのツールって思ってませんか?
inoueasei
1
140
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
300
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
440
霧の中の代数的エフェクト
funnyycat
1
470
Laravelで学ぶ Webアプリケーションチューニング入門/web_application_tuning_101
hanhan1978
4
1.7k
メールのエイリアス機能を履き違えない
isshinfunada
0
220
今さら聞けない .NET CLI
htkym
0
180
生成AIで帳票OCRが「簡単に」作れる時代になった?
kon_shou
0
490
Featured
See All Featured
Balancing Empowerment & Direction
lara
6
1.2k
Paper Plane
katiecoart
PRO
2
52k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
270
A better future with KSS
kneath
240
18k
sira's awesome portfolio website redesign presentation
elsirapls
0
320
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
200
Music & Morning Musume
bryan
47
7.3k
A Soul's Torment
seathinner
6
3.4k
It's Worth the Effort
3n
188
29k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
350
From π to Pie charts
rasagy
0
250
Transcript
React Native でRedux‑Saga を使ったりした 話 Tokyo Otaku Mode Internal Developers
Sesssion Aug 25, 2017 Hiroshi HORIKI @pchw
React Native で最近作ったアプリたち
React Native React の技術を使って,Native アプリを作れる シンプルなアプリを作るだけなら, 特にフレー ムワー クを入れる必要な く作れる.
アー キテクチャ導入の決定 「 アプリが複雑になることが決まっている」 「 そろそろ状態管理が辛くなってきた」 「 非同期の処理が多くなってきて, 特定のstate をどこの処理が変更
しているかわからなくなってきた」
Flux アー キテクチャ
Redux Flux 実装の1 つ 1 方向のデー タの流れ グロー バルな一つのImmutable State
上図のような概念を導入できる.
Redux 実装者が用意する必要があるのは, Action の一覧 Reducer というAction の種類によってState を更新し新しいState を 生成する処理
初期State の値 View であるComponent State を変更したい時にdispatch でAction を送出するようにする
Redux import { createStore } from 'redux'; import reducers from
'./reducers' const initialState = {...}; const store = createStore( reducers, initialState ); のようにして,Reducer と初期State の値を元にStore を作る. store.dispatch() とすれば, reducers がハンドリングして新しい State が生成されてStore の中身が更新される.
React‑Redux react‑redux というモジュー ルを入れることで, View である Component に Store へのアクセスやAction
をdispatch するための仕組 みを導入することができる. import { connect } from 'react‑redux'; class HogeComponent extends React.Component { render(){ const { somethingStateField, dispatch } = this.props; dispatch({type: ACTION_TYPES.HOGE_RENDERED}); } } export default connect(mapStateToProps)(HogeComponent)
React‑Redux トップレベルのComponent は特別に Provider というComponent で囲 んであげて, createStore で生成したstore をプロパティとして渡す必
要があります. import { Provider } from 'react‑redux'; import Hoge from './HogeComponent' export default class App extends Component { render() { return ( <Provider store={store}> <Hoge/> </Provider> ); } }
( やっと) Redux‑Saga の話
Redux‑Saga API 連携とかの機能が付いてくると, 非同期で処理を行い, その結果をま た別のAPI に投げて・・・ ということがあり, そこで導入すると良いの が
Redux‑Saga . Reducer Action で投げられたタイプによってState を変えて新しいState を作り出す 複雑な処理は行ってはならない Redux‑Saga Action で投げられたタイプによって処理を行い副作用を起こす 副作用をStore に反映するのはdispatch 経由.
Redux‑Saga
Redux‑Saga Action の待受は yield takeEvery(ACTION_TYPE_XXX, doSomethingX); yield takeEvery(ACTION_TYPE_YYY, doSomethingY); yield
takeEvery(ACTION_TYPE_ZZZ, doSomethingZ); みたいにする.
Redux‑Saga は何が嬉しいのか? generator を活用して書くため, 全て同期的に書ける 並行してのAction の待ち受けや,2 回目にAction が飛んできたら別 の処理をしたいということも簡単.
処理と処理を完全に分離して書ける API の呼び出しやState の取得・ 変更もRedux‑Saga のgenerator 関 数を経由して書くため, 処理をモックすることなくテストを簡潔に 書くことが出来る
Redux‑Saga の世界 redux‑saga/effects に色んなsaga の世界観を実現するためのAPI が 用意されている take fork select
call put を覚えておけば, 基本的なケー スに対応できる.
Redux‑Saga を使う準備 Redux 時代のコー ドから createStore のところを変更 import { createStore,
applyMiddleware } from 'redux'; import createSagaMiddleware from 'redux‑saga'; import rootSaga from './sagas'; const sagaMiddleware = createSagaMiddleware(); const store = createStore( reducers, initialState, applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga);
Redux‑Saga を使う準備 redux‑saga/effects から使うものをimport する. import { take, fork, select,
call, put, takeEvery, takeLatest} from 'redux‑saga/effects'
take: Action の待受 yield take(ACTION_TYPE_XXXX, doSomethingX); ACTION_TYPE_XXX を待ち受けて, doSomethingX を実行する.
待ち受けたり, 実行してる間には, 他のイベントを取りこぼす. 順次処理を行う時は, yield take(ACTION_TYPE_START_STAGE, startStageOne); yield take(ACTION_TYPE_START_STAGE, startStageTwo); みたいにすると,1 つ目の take が終わったら2 つ目の take で待受にな るので, 同じイベントでも2 回目で処理を変える( この場合はステー ジ2 が始まる) ことができる.
fork: 平行世界を作る 前述の take だけだと, 並行してAction を待ち受けず, 処理している間 にAction を取りこぼしたりする.
そこで, fork を使う.
fork: 平行世界を作る yield fork(function*(){ yield take(ACTION_TYPE_START_STAGE, startStageOne); }) yield fork(function*(){
yield take(ACTION_TYPE_ENCOUNT_CHALLENGER, encountChallenger); }) のようにすると, yield fork はすぐに制御が返ってきて, 裏では指定 した関数が実行される. 1 つめの fork で ACTION_TYPE_START_STAGE を待ち受ける. fork はすぐに制御を返すので, そのまま2 つめの fork へ進 み, ACTION_TYPE_ENCOUNT_CHALLENGER も待ち受ける. これで, ステー ジの開始のアクションもハンドリング出来るし, 並行し て乱入者が来たかどうかをハンドリングすることも出来る.
takeEvery take は1 度Action を受け取ったらそれで終わり. タップ入力などの何度もAction をハンドリングする必要が有る場合は yield fork(function*(){ while(true){
yield take(ACTION_TYPE_MOVE_LEFT, moveLeft); } }); のように,while ルー プで何度も待ち受けるというようなことをしないと いけない. Redux‑Saga はヘルパー を用意していて, 上記と同様の fork してwhile ルー プで待ち受けるような処理を yield takeEvery(ACTION_TYPE_MOVE_LEFT, moveLeft); と書くだけで実現できる.
takeLatest 検索バー のインクリメンタル検索のように, 次の入力があったら最後の 入力だけで処理をしたいというときに使えるのが takeLatest yield takeLatest( ACTION_TYPE_SEARCH_BAR_CHANGED,searchProduct); イベントのたびに
searchProduct が呼ばれる. 処理中に同じAction が再度飛んできた場合, 前回のタスクをキャンセル して新しく searchProduct を実行する. takeEvery と同様に, fork 作用と while で継続的に待ち受ける機 能も有しているので, 上記のように書くだけで別のAction の待受と並行 で待ち受けることが出来る.
select: Store からstate を読み出す take して実行している関数の中で Store に格納された state が使い
たい場合は select を使って読み出すことが出来る. const searchProduct = function*(){ const state = yield select(); }
call: 非同期の関数を呼び出す 外部にアクセスするAPI などを叩く時などは call を使う const searchProduct = function*(){
const state = yield select(); const result = yield call( API.findProduct, {q: state.searchText}); } テストの簡便さのために, yield API.findProduct({q: state.searchText}) ではなく, call で囲んで呼ぶ. call を経由しないで行う場合は, テスト時に API.findProduct が返 すPromise がどのような状態だとテストがPass なのかが難しく, 外部に アクセスする場合はAPI をモックが必要 call を使うと, タスクのオブジェクトが返り, それを assert すれば テストができる.
put タスク内で得られた結果を Store に反映させたい場合は put を使っ て,Action をdispatch する. 新しいState
を作成し,Store を変更するのはReducer の責務. const searchProduct = function*(){ const state = yield select(); const result = yield call( API.findProduct, {q: state.searchText}); yield put({ type: ACTION_TYPE_SEARCH_COMPLETE, payload:{products: result.products} }); }
図にまとめると
まとめ Redux‑Saga を使うと非同期のややこしい処理が分割出来て同期 的に書けて捗る React Native でも使える 仕組み的には,redux のvue 版であるVuex
などにも応用出来そう?