Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Redux Middleware Wars (Japanese)
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Shuhei Kagawa
July 14, 2016
Technology
2k
8
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Redux Middleware Wars (Japanese)
M3 Tech meetup! #2 ~フロントエンドの副作用~
http://m3-engineer.connpass.com/event/33802/
Shuhei Kagawa
July 14, 2016
More Decks by Shuhei Kagawa
See All by Shuhei Kagawa
Profiling Node.js apps on production
shuhei
0
970
Building a Pixel Art Editor with Elm
shuhei
1
890
Redux Middleware Wars (English)
shuhei
0
220
Draw Animated Chart on React Native
shuhei
0
9k
Angular 2 Offline Compiler
shuhei
0
5.5k
Weird Attractors
shuhei
0
950
Angular 2 @ JS Ojisan #6-3
shuhei
1
3.1k
Introduction to Angular 2
shuhei
2
190
Git の内部データ構造
shuhei
2
2.1k
Other Decks in Technology
See All in Technology
「どのログを見ればいい?」 から始めた サーバーレス障害解析
y_waka1
1
150
AIで社員の自主発信に広報目線を組み込む
_mossann_t
0
150
10年欲しかった音楽管理アプリを、AIと一緒に作りはじめた
judau
1
130
リアーキテクチャ後の障害ゼロを目指したShadow Testingの取り組み
nihonbuson
PRO
1
180
SREの視点で考えるSIEM活用術 〜AWS環境でのセキュリティ強化〜
cscengineer
PRO
0
380
エージェントはローカル、検証はMicroVM — Lambda MicroVMsでつくるServerless CI
fujioka6789
3
820
GitHub Agentic Workflows を触ってみる
htkym
2
730
Kiro Meetup #8 Kiro アップデート (2026/3/21〜2026/9/24)
katzueno
1
270
Oracle Cloud Infrastructure(OCI):Onboarding Session(はじめてのOCI/Oracle Supportご利⽤ガイド)
oracle4engineer
PRO
3
21k
Amazon Bedrock Agents ClassicからAmazon Bedrock AgentCoreへ移行した際、ガードレール設定が2箇所に割れた話
matsunobu
0
120
Snowflake Horizon Catalog と Apache Iceberg で作る オープンなデータ基盤
kitagawaz
0
120
【技術的負債conf】事業成長に伴う技術的負債の説明責任とAIによるモニタリング、認知的負債について
i35_267
4
2.2k
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Optimising Largest Contentful Paint
csswizardry
37
4k
We Are The Robots
honzajavorek
0
380
A better future with KSS
kneath
240
18k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Thoughts on Productivity
jonyablonski
76
5.4k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
Scaling GitHub
holman
464
140k
30 Presentation Tips
portentint
PRO
1
410
The Language of Interfaces
destraynor
162
27k
Transcript
Redux Middleware Wars
Me • So$ware Engineer at M3, Inc. • ҩྍݱͰ͏γεςϜͷ։ൃ •
AngularJS, Rails, Node.js, Babel, etc. • GitHub, Qiita: @shuhei • TwiGer: @shuheikagawa • ! Ϗʔϧݕఆ 2 ڃ
Middleware ʹ͍ͭͯͦ͢ͷલʹɾɾɾ
ͦͦ Redux ͱʁ • Predictable state container for JavaScript apps
• ༧ଌՄೳͳঢ়ଶίϯςφʢ༁ʣ • ͱͱ Time traveling, hot reloading Λతͱͯ͠࡞ΒΕͨ Flux తͳԿ͔
Redux ͷ 3 ݪଇ 1. ΞϓϦͷશঢ়ଶΛҰͭͷ Object (State) ͱͯ͠อ࣋ 2.
Action ΛૹΔʢdispatchʣ͜ͱʹ ΑͬͯͷΈ State ΛมߋͰ͖Δʢͱ͍ ͏͔৽͍͠ State ͕࡞ΒΕΔʣ 3. Reducer ͱ͍͏ pure ͳؔʢಉ͡Ҿ ʹରͯ͠ৗʹಉ͡ฦΓΛฦ͢ʣʹ ΑͬͯͷΈঢ়ଶ͕มߋ͞ΕΔ reducer : (State, Action) -> State
! Pure ͳؔͱʁ • ҾͷΈʹΑͬͯฦΓ͕ܾ·Δ • ؔͷ֎ͷঢ়ଶΛมߋ͠ͳ͍ʢ෭࡞༻͕ͳ͍ʣ
! Pure ͡Όͳ͍ؔ • ࣌ʹΑͬͯฦ͕͢ҧ͏ • ฦΓ͕ͳ͍ • ҾΛมߋͯ͠͠·͏ •
ޙͰίʔϧόοΫ͕ݺΕΔ • etc.
Β͵ؒʹΞϓϦ ͷঢ়ଶ͕มΘΔ͜ ͱ͕ͳ͍
None
ͱ͍͑ɺ෭࡞༻Ͳ͏͢Δͷʁ • AJAX • local storage • cookie • ϩά
• etc.
• Reducer ͷதʹॻ͘: ແཧ • View Component ͷதʹॻ͘: ͔ͤͬ͘ঢ়ଶΛ͍ग़ͨ͠ͷ ʹɾɾɾ
• Ac4on Creator ͷதʹॻ͘: dispatch Λ͢ඞཁ͋Γ
Middleware
Redux Middleware ͱ • dispatch ͷલޙʹॲཧΛڬΉ • Action Λड͚ͯɺΰχϣΰχϣͰ͖ Δ
• Action ΛͪΐͬͱΒͤͯૹΔ • ผͷ Action ʹஔ͖͑Δ • ඇಉظॲཧΛߦ͍ɺ݁ՌΛ Action ͱͯ͠ૹΔ • e.g. WSGI, Rack, Express, Koa, etc.
ྫ: ͳʹ͠ͳ͍ ड͚औͬͨ Ac$on Λͦͷ··࣍ͷ middleware ʹ͛Δ const passthrough =
store => next => action => { return next(action); };
ྫ: ϩάΛग़ྗ ࣍ͷ middleware ʹ ac+on Λ͛ΔʢnextʣલޙͰϩάΛग़ྗ const logger =
store => next => action => { console.log('prev state', store.getState()); console.log('action', action); const returnValue = next(action); console.log('next state', store.getState()); return returnValue; };
ྫ: Promise ͷ݁ՌΛͭ const promise = store => next =>
action => { if (typeof action.then === 'function') { return action.then(store.dispatch); } else { return next(action); } }; function fetchPosts() { return fetch('/posts').then(res => res.json()) .then(posts => ({ type: 'POSTS_FETCHED', posts })); } dispatch(fetchPosts);
ࠓճඇಉظॲཧΛߦ͏ Middleware ʹয
΄͍͠ͷ • ! ςετͷ͢͠͞ʢϞοΫແ͠ͰςετͰ͖Δͱ࠷ߴʣ • " ۭ࣌Λ͑Δʢthro'ling, debouncingʣ • #
ϩδοΫͷڽू • ✨ ։ൃͷ׆ൃ͞
ඇಉظॲཧΛߦ͏ Middleware ಠஅͱภݟʹΑΓ... | ----------------- | ---- | --------- |
---- | ---- | ---- | ---- | | name | star | from | test | time | cohe | acti | | ----------------- | ---- | --------- | ---- | ---- | ---- | ---- | | redux-thunk | 2392 | '15/07/13 | C | C | B | A | | redux-promise | 864 | '15/07/02 | - | C | C | C | | redux-saga | 3172 | '15/11/30 | B | A | A | A | | redux-loop | 641 | '16/01/06 | A | C | B | C | | redux-observable | 634 | '16/02/16 | C | A | B | A | | ----------------- | ---- | --------- | ---- | ---- | ---- | ---- | ⭐ ͷ 2016/7/5 ௐ
redux-thunk ⭐2392 Ac#on ͱͯؔ͠ʢthunkʣ͕དྷͨΒɺͦΕΛ࣮ߦ͢ΔʢҾʹ dispatch ͱ getStateʣ const fetchBeers =
() => (dispatch, getState) => { return fetch('/beers') .then(res => res.json()) .then(items => dispatch('FETCH_BEERS_SUCCEEDED', items)) .catch(error => dispatch('FETCH_BEERS_FAILED', error)); }; dispatch(fetchBeers());
redux-thunk ⭐2392 • ! ϞοΫ͠ͳ͍ͱςετ͕ॻ͚ͳ͍ • " Ac%on ΛҰ͔ͭͮͭ͠ड͚ΒΕͳ͍ͷͰɺdebounce ͳͲ͕
͍͠ • # ΄Ͳ΄ͲʹෳࡶͳϩδοΫॻ͚Δ • ✨ ΄Ͳ΄Ͳʹϝϯς͞Ε͍ͯΔɻͦͦ 13 ߦ͔͠ͳ͍ • ࢀߟ: How to dispatch a Redux ac%on with a %meout?
redux-promise ⭐864 FSA (Flux Standard Ac/on) ͷ payload ͷ promise
Λղܾ͠ɺ Ac/on ͱͯ͠ૹΓͯ͘͠ΕΔ function fetchItems() { const promise = fetch('/items').then(res => res.json()); return { type: 'FETCH_ITEMS', payload: promise }; } dispatch(fetchItems());
redux-promise ⭐864 • ! γϯϓϧͳͷͰɺͦ͜·Ͱςετ͠ͳͯ͘ྑͦ͞͏ • " debounce ͳͲͰ͖ͳ͍ •
# ෳࡶͳϩδοΫॻ͚ͳ͍ • ✨ 4 ϲ݄ఔϝϯς͞Εͯͳ͍ɻ25 ߦ͚͕ͩͩɾɾɾ • Τϥʔॲཧͷൺֱతॏཁͦ͏ͳ MR ͕Ϛʔδ͞Ε͕ͨϦϦʔ ε͞Ε͍ͯͳ͍
redux-saga ⭐3172 Saga ͱݺΕΔ generator (saga) Ͱ෭࡞༻Λ͏ॲཧΛهड़ function* fetchBeer(action) {
try { const beers = yield call(fetchBeer, action.id); yield put({ type: 'FETCH_BEER_SUCCEEDED', payload: beers }); } catch (error) { yield put({ type: 'FETCH_BEER_FAILED', error }); } } function* watchFetchBeer() { yield* takeEvery('FETCH_BEER', fetchBeer); }
redux-saga ⭐3172 • ! ςετ͕͍͢͠ʂʂʂ • ෭࡞༻ϦΫΤετΛ yield ͯ͠ɺmiddleware ʹ࣮ߦͯ͠
Β͍ɺ݁ՌΛड͚औΔ • ࣗ pure ͳ··ෳࡶͳඇಉظॲཧ͕ॻ͚Δ • ৄ͘͠ @kuy ͞Μͷ͓Ͱɾɾɾ
redux-loop (store enhancer) ⭐641 Elm Λਅࣅͨ APIɻreducer ͕ state ͚ͩͰͳ͘
Effects ฦ͢ function beers(state = [], action) { switch (action.type) { case 'FETCH_BEERS': return loop(state, Effects.promise(fetchBeers)); case 'FETCH_BEERS_SUCCEEDED': return action.payload; default: return state; } }
redux-loop (store enhancer) ⭐641 • ! ϞοΫͳ͠ͰςετͰ͖Δ • Effects ͨͩͷ
Objectɻ࣮ߦ͢Δ·Ͱ෭࡞༻ى͖ͳ͍ • " debounce ͳͲͰ͖ͳͦ͞͏ • # Effects ΛΈ߹ΘͤΔ͜ͱ͕Ͱ͖Δ • ✨ 3 ϲ݄΄Ͳϝϯς͞Ε͍ͯͳ͍ɻ࡞ऀ͕ Elm ͔͠ॻ͔ͳ͘ ͳͬͯ͠·ͬͨʁ
redux-observable ⭐ 634 reducer ͷޙͰ Action Λड͚ͯ Action Λग़ྗ͢Δ Observable
Λฦ͢ function beerEpic(action$, store) { const beers$ = action$.ofType('FETCH_ITEMS') .mergeMap(() => Observable.fromPromise(fetchBeers())) .map(beers => ({ type: 'FETCH_BEERS_SUCCEEDED', payload: beers })); return Observable.merge( beers$, something$ ); }
redux-observable ⭐ 634 • ! ϞοΫ͠ͳ͍ͱςετͰ͖ͳ͍ • " Rx ͷڧྗͳ
operator Ͱ༰қʹۭ࣌Λ੍ͤΔ • # redux-saga తͳ background processor style ʹਐԽ • ෳࡶͳॲཧॻ͚Δ • ✨ ݱࡏ։ൃதɻͱͯγϯϓϧ • Rx ΩϚΔͱؾ͍͍࣋ͪʢݸਓͷײʣ
τϨϯυʢʁʣ • σʔλͱͯ͠ͷ෭࡞༻ʢsaga, loop, Cycle.jsʣ • ෭࡞༻ϦΫΤετΛ middleware ͕ॲཧ͢Δ •
։ൃऀ͕ॻ͘ϩδοΫ͕៉ྷʹอͯΔ • Background processor ελΠϧʢsaga, observable, chooʣ • reducer ͷલͰͳ͘ޙͰ Action Λड͚Δ
࠙ձͰ͍Ζ͍Ζڭ͑ͯԼ͍͞ʂ
Thanks!
Credits • Chart of Redux from h0p:/ /www.bebe0erdeveloper.com/coding/ ge=ng-started-react-redux.html