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
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
540
Go を使い始めて 2 ヶ月の学び / My first two months with Go
contour_gara
0
390
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
170
AIと壁打ちしながら進めるコスト管理
fufuhu
2
1.8k
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
270
書籍「プロフェッショナルAI駆動開発」紹介スライド
juntaromatsumoto
0
710
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
280
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
250
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
250
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
740
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
410
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
170
Featured
See All Featured
The untapped power of vector embeddings
frankvandijk
2
1.8k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
45k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.5k
Become a Pro
speakerdeck
PRO
31
6.2k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
790
Git: the NoSQL Database
bkeepers
PRO
432
67k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
560
WENDY [Excerpt]
tessaabrams
11
39k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
490
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
などにも応用出来そう?