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
redux-pluto
Search
Yosuke Furukawa
PRO
April 19, 2018
Programming
4.6k
18
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
redux-pluto
Folio Scramble! #1 で話した redux best practiceの話です。
Yosuke Furukawa
PRO
April 19, 2018
More Decks by Yosuke Furukawa
See All by Yosuke Furukawa
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
350
デザインシステムが必須の時代に
yosuke_furukawa
PRO
2
250
Node.js, Deno, Bun 最新動向とその所感について
yosuke_furukawa
PRO
10
5.3k
Welcome JSConf.jp 2024
yosuke_furukawa
PRO
1
4.8k
tc39 x jsconf.jp Panel Discussion 2024
yosuke_furukawa
PRO
0
360
Removing Corepack
yosuke_furukawa
PRO
9
2k
JavaScript Runtime とはなにか
yosuke_furukawa
PRO
15
3.2k
Strip Types と Storage
yosuke_furukawa
PRO
4
530
Module Harmony について
yosuke_furukawa
PRO
4
1.9k
Other Decks in Programming
See All in Programming
リアルな遅延を測る仕様
kota_yata
1
120
What's New in Android 2026
veronikapj
0
270
仕様駆動開発の消費期限
watany
20
8.8k
2年かけて Deno に DOMMatrix を実装した話 / How I implemented DOMMatrix in Deno over two years
petamoriken
0
220
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
120
170k Jobs a Day on GKE: Scaling Mercari's CI Platform - and What's Next for AI-Native Development
junyaokabe
0
120
VibeCodingからAgenticWorkflowへ
starfish719
0
730
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
570
Go 1.27 における memory allocation の高速化
andpad
0
290
AIを紡ぐPMのお話
swdtkuy
0
120
生成AIで帳票OCRが「簡単に」作れる時代になった?
kon_shou
0
1.1k
ここ半年くらいでAIに作らせたR用ツール
eitsupi
0
400
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
4 Signs Your Business is Dying
shpigford
187
23k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
480
ラッコキーワード サービス紹介資料
rakko
1
4.5M
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
440
How GitHub (no longer) Works
holman
316
150k
Documentation Writing (for coders)
carmenintech
77
5.5k
Side Projects
sachag
455
43k
Navigating Team Friction
lara
192
16k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.8k
Code Review Best Practice
trishagee
74
20k
Transcript
redux-pluto 2018/04/19 @ Folio Meetup # Scramble! #1
Twitter: @yosuke_furukawa Github: yosuke-furukawa
redux-pluto • ϦΫϧʔτςΫϊϩδʔζࣾͰ։ൃதͷϘΠϥʔϓ Ϩʔτ • େن։ൃ͚ɺϕετϓϥΫςΟεΛूΊͨ ͷ • ͪͳΈʹ·ͩ։ൃதͳͷͰࠓϦϙδτϦެ ։Ͱ͖ͳ͍Ͱ͢ɺӶҙקΊதͰ͢ɻ
͍͢·ͤΜɺɺɺ
redux-pluto • ϦΫϧʔτςΫϊϩδʔζࣾͰ։ൃதͷϘΠϥʔϓ Ϩʔτ • େن։ൃ͚ɺϕετϓϥΫςΟεΛूΊͨ ͷ • ͪͳΈʹ·ͩ։ൃதͳͷͰࠓϦϙδτϦެ ։Ͱ͖ͳ͍Ͱ͢ɺӶҙקΊதͰ͢ɻ
͍͢·ͤΜɺɺɺ ࠓ͜ͷϕετϓϥΫςΟεΛ νϥݟͤ
ϕετϓϥΫςΟε ΞʔΩςΫνϟฤ
ϕετϓϥΫςΟε 1 ඇಉظσʔλϩʔυ
ඇಉظσʔλϩʔυ • redux-async-loader • SSRͰCSRͰಈ͘σʔλFetchؔΛఏڙ ͯ͘͠ΕΔ • σʔλFetchதReactͷrenderΛ͠ͳ͍࡞Γ
ඇಉظσʔλϩʔυ • redux-async-loader import { compose } from 'recompose'; export
default compose( // CSR Ͱ SSR Ͱ྆ํಈ͘ // σʔλ͕ϩʔυ͞ΕͯΔͱloading state͕trueʹͳΓɺͦͷظؒ // component͕render͞Εͳ͍ɻ asyncLoader((props, { dispatch }) => dispatch(loadUsers(props))), connect({ ... }, { ... }) )(class UserList exptends React.Component { // ... });
ඇಉظσʔλϩʔυ • ଞͷOSSࣄྫ • CyberAgent: https://github.com/kouhin/redux- dataloader • Next.js: getInitialProps
https://github.com/zeit/ next.js/blob/master/examples/with-redux/pages/ index.js#L8-L13 • Nuxt.js: asyncData
ඇಉظσʔλϩʔυ • Ͳͷํ๏Ͱ͍͍ͩͨಉ͕ͩ͡ɺredux-async- loaderͲ͜ͷίϯϙʔωϯτ͔ΒͰඇಉظ σʔλϩʔυͰ͖Δɻ • Next.js, Nuxt.js ͷͷRootͰͷΈൃՐՄೳ •
େن։ൃͩͱ్தͷComponent͔ΒͰඇಉ ظϩʔυͰ͖Δํ͕خ͍͜͠ͱɻ
ϕετϓϥΫςΟε 2 reduxϑϩʔ੍ޚ
reduxϑϩʔ੍ޚ • redux-effects-steps https://github.com/recruit-tech/redux-effects-steps • redux-thunksagaɺObservableͱ͍͏खஈ͕͋Δ ͕ͦΕΒͬͯͳ͍ɻ • ϑϩʔ੍ޚͰෳࡶͳॲཧΛॻ͚ΔΑ͏ʹͨ͘͠ͳ͍ •
ෳࡶʹͳͬͯ͠·͏ͷͰ͋Εmiddlewareʹಀ͕͢
reduxϑϩʔ੍ޚ • redux-effects-steps https://github.com/recruit-tech/redux-effects-steps • import { createAction } from
'redux-actions'; import { steps } from 'redux-effects-steps'; import { fetchrRead } from 'redux-effects-fetchr'; const fetchUserRequest = createAction('FETCH_USER_REQUEST'); const fetchUserSuccess = createAction('FETCH_USER_SUCCESS'); const fetchUserFail = createAction('FETCH_USER_FAIL'); function fetchUser({ user }) { return steps( // ϦΫΤετͨ͠ΒϦΫΤετͨ͜͠ͱΛActionͰൃՐ͓ͤͯ͘͞ɻ fetchUserRequest(), // ຊϦΫΤετ fetch ॲཧ fetchrRead('users', { user }), // ޭͨ͠ΒSuccess Action, ࣦഊͨ͠Β Failure Action [fetchUserSuccess, fetchUserFail] ); }
reduxϑϩʔ੍ޚ • ଞͷOSSࣄྫ • redux-thunk • redux-saga • redux-observable
reduxϑϩʔ੍ޚ • redux-thunkԿͰͰ͖͗͢ΔɺActionΛॻ͘ॴͰࡉ͔͍ॲ ཧ͕ॻ͚ΔͷΓա͗ײ͋Δɻ͕ͦ͜Ԛ͘ͳΓͦ͏ɻ • redux-sagasagaͱ͍͏ϨΠϠͰόοΫάϥϯυϓϩηε తʹԿͰΔɻ͜͜·Ͱͷॲཧ͕ඞཁʹͳͬͨέʔε͕গͳ ͍ɺΑ͋͘ΔͷϦΫΤετΛൃՐͯͦ͠Ε͕ޭ͔ࣦͨ͠ഊ ͔ͨ͠ఔɺͦΕ͚ͩͰsagaΦʔόʔΩϧײ •
observableRxJSͰྲྀΕΛ੍ޚ͢Δͱ͍͏ͷ͕ͩɺͦ͜· Ͱͷྲྀྔ੍ݶ͕ඞཁʹͳͬͨ͜ͱ͕ͳ͍
ϕετϓϥΫςΟε 3 ducks
ducks • https://github.com/erikras/ducks-modular- redux • reducer, actions, action creatorͱ͍͏ػೳͰ ͚ΔͷͰͳ͘ɺUserɺArticleͱ͍ͬͨΑ
͏ͳϦιʔεͷѻ͍Ͱ̍ͭͷϑΝΠϧʹ͢Δ
ducks • https://github.com/erikras/ducks-modular- redux /* @flow */ /** * Initial
State */ const SALON = "redux-proto/salon"; export const [ FIND_SALON_BY_ID_REQUEST, FIND_SALON_BY_ID_SUCCESS, FIND_SALON_BY_ID_FAIL ] = createAsyncActionTypes(`${SALON}/find_id`); /** * Action creators */ const findSalonByIdRequest = createAction(FIND_SALON_BY_ID_REQUEST); const findSalonByIdSuccess = createAction(FIND_SALON_BY_ID_SUCCESS); const findSalonByIdFail = createAction(FIND_SALON_BY_ID_FAIL);
ducks • https://github.com/erikras/ducks-modular- redux /* @flow */ /** * Reducer
*/ export default (handleActions( { [FIND_SALON_BY_ID_REQUEST]: state => ({ … }), } )) /** * Selector */ export default (createSelector((state) => {…}, (items) => {…}))
ducks • actions, action creator, reducer ͚ͩͰͳ͘ɺselector· Ͱதʹ࣋ͭɻ • ϑΝΠϧ͕େ͖͘ͳΓͦ͏ͳ࣌ϑΥϧμʹͯ͠ϑΝΠϧ
ׂ͢Δͷ༗Γɻ͜ͷล͖ʹ • re-ducksͱ͍͏ͷ͋Δ͕ɺ͜ΕͱͷϋΠϒϦουײɻ • ཁΓ͍ͨͷϦιʔε࣠Ͱ·ͱΊΔํ͕ػೳ࣠Ͱ·ͱ ΊΔΑΓॻ͖͘͢ɺݟ͔ͬͨ͢ɻ
ϕετϓϥΫςΟε 4 APIఆٛ
APIఆٛ • agreed https://github.com/recruit-tech/ agreed • Consumer Driven ContractΛ࣮ફ •
ϑϩϯτΤϯυ͕த৺ʹͳͬͯ։ൃΛ͢͢Ί ΔΈʹͳ͍ͬͯΔɻ
APIఆٛ • agreedͰAPIͷmockΛઌʹ࡞ • mockΛ࡞ΓऴΘͬͨΒAPI࡞ऀ(Server Side)ʹagreed-uiͰཁٻΛڞ༗ɻ • API͕ߏஙͰ͖͖ͯͨΒagreed-clientͰςετ έʔεͱ࣮ͯ͠ߦ͞ΕΔɻ
APIఆٛ
APIఆٛ • ଞOSSࣄྫ • Swagger • Pact
APIఆٛ • SwaggerAPIͷ༷ఆٛͰ͋ͬͯAPIͷཁٻ Ͱͳ͍ɻ͋͘·ͰυΩϡϝϯτɺmock࡞ ΕΔ͕࡞Γ͘͢ͳͦ͞͏ɻ • Pactclientͷςετσʔλ͔Βserverͷ νΣοΫΛ͢ΔͨΊͷσʔλΛࣗಈੜ͢Δ Έɻςετσʔλ͕ඞཁͳͷਏ͍ɻɻ
ϕετϓϥΫςΟε UIฤ
ϕετϓϥΫςΟε ϑΥʔϜ
ϑΥʔϜฤ • 2017ͷformʹ͍ͭͯ • https://speakerdeck.com/yosuke_furukawa/ 2017nian-falseformfalsehua
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY +BWB4DSJQUͷϝϞϦ
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY +BWB4DSJQUͷϝϞϦ 6ODPOUSPMMFE 'PSN $POUSPMMFE
'PSN
Uncontrolled vs Controlled • DOMͷΛ͏ (Uncontrolled) • DOM͔Βऔ͖ͬͯͨΛJSͷϝϞϦʹೖΕ ͯɺεφοϓγϣοτͱͯ͠͏ (Controlled)
Uncontrolled form // React ͩͱ͜͏ class NameForm extends React.Component {
// … handleSubmit(event) { alert('A name was submitted: ' + this.input.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" ref={(input) => this.input = input} /> </label> <input type="submit" value="Submit" /> </form> ); } }
Controlled form class NameForm extends React.Component { // … handleChange(event)
{ this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleCha </label> <input type="submit" value="Submit" /> </form> ); } }
Uncontrolled vs Controlled • Controlled ͳํ ͜͜Ͱ React ͷ state
ͱ ͯ͠ཧ͢Δ • Uncontrolled ͳํDOMʹ͚ͩཧͤ͞Δ
Uncontrolled vs Controlled • Facebook ͕ਪͯ͠Δͷ Controlled Ұ • React
ͷ v-dom ߋ৽ͷλΠϛϯάͱ߹Θͤͯ React ͕࠷దԽͨ͠ํ๏ͰDOMʹөͤ͞Δ͜ͱ ͕Ͱ͖Δ • ͪΐͬͱڽͬͨformΛ࡞ΕେମControlledͰ࣮ ͢Δඞཁ͕ग़ͯ͘Δɻ
Uncontrolled vs Controlled • jQuery UI Έ͍ͨͳϥΠϒϥϦେମ Uncontrolled ͳํ๏ͰͬͯΔ͜ͱ͕ଟ͍ʢؾ ͕͢Δʣ
• طଘͷࢿ࢈͕jQueryʹ͋ͬͯͦΕ͕ Uncontrolled ͳํ๏Ͱ࣮ݱ͞ΕͯΔͳΒ͏ͷ ྑ͍͕ɺجຊ Controlled Ͱྑ͍ؾ͕͢Δɻɹ
Uncontrolled vs Controlled • https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY +BWB4DSJQUͷϝϞϦ 6ODPOUSPMMFE 'PSN ͏Εͯྑ͍͔
$POUSPMMFE 'PSN ͓ͬͪ͜͢͢Ί
Ͱ 2017 ݱࡏ state ͕ ෳ͋Δ
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%#
Ͳ͜ʹΛอଘ͢Δͷ͕ਖ਼͠ ͍ͷ͔ʁ
None
6TF3FBDUGPSFQIFNFSBMTUBUFUIBUEPFTO`UNBUUFSUPUIF BQQHMPCBMMZ
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# &QIFNFSBM
&UFSOBM 'PSFWFS
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# Ұ࣌తͳGPSNͷ
ͳΒ͜͜ʹ HMPCBMͳTUBUFͳΒ ͜͜ʹ
ͰͬͯΈΔͱ
React ͷ state ͱ Redux ͷ state Ͱ form ͔ͩΒͱ͍ͬͯ
͚Δͷ໘
ࠓ
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# ͳΜ͔ύϑΥʔϚϯεͷϘ
τϧωοΫ͕͋ͬͨΒ͜͜ جຊ͜͜
twitter Lite ͷߏ
ࠓͷ form ͷΛཧ͢Δॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# UXJUUFSͷGPSNͷใ
Ұ୴͜͜ͰCV⒎FS จࣈهड़ͨ͠Β SFEVDFSʹߦ͘
͋Δఔ form ͷใ React ͰͨΊͯɺจࣈೖΕ ͨΒ Redux ʹ flush ͤ͞Δɻ
ϕετϓϥΫςΟε ԾεΫϩʔϧ
ԾεΫϩʔϧ • େલఏ: • DOMͷཁૉ͕૿͑Ε૿͑Δ΄Ͳϖʔδ ॏ͘ͳΔ͠ɺΧΫͭ͘ • ϒϥβ্ͷϝϞϦ͕େ͖͘ͳΔ • ݟ͑ͯͳ͍ॴDOMʹදࣔ͠ͳ͍͍ͯ͘
ԾεΫϩʔϧ • ݟ͑ͯΔͱ͜Ζ͚ͩDOMͱͯ͠දࣔ͢Δ • react-virtualized Λ͏ %0.ͱͯ͠ දࣔ %0.͔Β ഁغ
ϕετϓϥΫςΟε ແݶεΫϩʔϧ
ແݶεΫϩʔϧ • େલఏ: • Ϣʔβʔͷճ༡࣌ؒΛ૿͍ͨ͠ɻ ݕࡧͨ͠Β2ϖʔδҎ߱ͪΌΜͱݟ͍ͤͨɻ • ͪ·ͪ·࣍ͱ͔ϖʔδͷϦϯΫΛԡ͞ͳ͖Ό͍͚ͳ͍ͷ໘ ʢಛʹϞόΠϧʣ •
͔ͱݴͬͯSEOઈରʢεΫϩʔϧ͢ΔͷϢʔβʔ͚ͩͰ Google CrawlerεΫϩʔϧΠϕϯτ·ͰൃՐͯ͘͠Εͳ͍ʣ
ແݶεΫϩʔϧ • ແݶεΫϩʔϧ x ϖʔδωʔγϣϯ • ϢʔβʔΫϩʔϥʔ ྆ํϑϨϯυϦʔʹɻ Δ 1
2 3 4 5 6 7 8 9 10 ࣍
όουϊϋ ͬͯΈ͚ͨͲμϝͩͬͨฤ
ϋϚΓ·ͬͨ͘ babel plugins
babel-plugin-transform-react- inline-elementsͰIEͷࢮ
transform-react-constant- elementsͰbabelόάΛ౿Ή
transform-react-constant- elementsͰbabelόάΛ౿Ή • ൵C
Α͘Α͘ߟ͑Δͱͨ͘͞Μ͋Δ • fetchrͷෆ۩߹Λ౿Μͩ ʢओʹηΩϡϦςΟ໘ʣ • React v15ͰϝϞϦʔϦʔΫʹ·͞ΕΔɺv16Ͱղফ • react-router v4ະରԠ
• etc…
Α͘Α͘ߟ͑Δͱͨ͘͞Μ͋Δ • fetchrͷෆ۩߹Λ౿Μͩ ʢओʹηΩϡϦςΟ໘ʣ • React v15ͰϝϞϦʔϦʔΫʹ·͞ΕΔɺv16Ͱղফ • react-router v4ະରԠ
• etc… ܾͯ͠ॱ෩Ͱͳ͍͕ɺԶΒͬ ͍ͯͧ͘ʂʂʂʂ
·ͱΊ • ϕετϓϥΫςΟεʢΞʔΩςΫνϟฤʣ • ඇಉظϩʔυ • reduxϑϩʔ੍ޚ • ducks •
APIఆٛ • ϕετϓϥΫςΟε(UIฤ) • ϑΥʔϜ • ԾεΫϩʔϧ • ແݶεΫϩʔϧ • όουϓϥΫςΟε • babel plugin…, onlyUpdateForPropTypes…, etc