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
18
4.2k
redux-pluto
Folio Scramble! #1 で話した redux best practiceの話です。
Yosuke Furukawa
PRO
April 19, 2018
Tweet
Share
More Decks by Yosuke Furukawa
See All by Yosuke Furukawa
Module Harmony について
yosuke_furukawa
PRO
3
1.4k
LTのやり方
yosuke_furukawa
PRO
15
1.8k
AppRouter Panel Talk
yosuke_furukawa
PRO
3
620
Node.js v22 で変わること
yosuke_furukawa
PRO
13
4.7k
リアーキテクトと開発生産性について
yosuke_furukawa
PRO
25
8.9k
JavaScript Server Runtime History
yosuke_furukawa
PRO
8
3.4k
tc39 x jsconf.jp Panel Discussion
yosuke_furukawa
PRO
0
1.5k
フロントエンドの開発生産性とは
yosuke_furukawa
PRO
18
10k
7 principles for rich web apps And how next.js achieves these principles
yosuke_furukawa
PRO
6
2.8k
Other Decks in Programming
See All in Programming
Rubyのパフォーマンスプロファイリングの改善 / Enhancing performance profiling for Ruby
osyoyu
1
410
リハビリmruby
kishima
1
160
ドメイン駆動設計の実践
masuda220
PRO
19
5.2k
Folding Cheat Sheet #7
philipschwarz
PRO
0
150
12年前の『型システム入門』翻訳の思い出話
mame
11
1.2k
The rollercoaster of releasing an Android, iOS, and macOS app with Kotlin Multiplatform | droidcon Berlin
prof18
0
110
CSC307 Lecture 10
javiergs
PRO
0
310
CSC307 Lecture 11
javiergs
PRO
0
240
Google's Recipe for Scaling (Web) Security – LocoMocoSec 2024
lweichselbaum
0
170
DMMプラットフォームにおけるTiDBの導入から運用まで
pospome
7
3k
CSC307 Lecture 08
javiergs
PRO
0
330
ピグパーティにおけるMongoDB CommunityバージョンからAtlasへの移行事例
10969hotaka
0
130
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
78
8.5k
The Straight Up "How To Draw Better" Workshop
denniskardys
229
130k
Facilitating Awesome Meetings
lara
46
5.8k
The Cult of Friendly URLs
andyhume
75
5.9k
We Have a Design System, Now What?
morganepeng
46
7k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
245
1.2M
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
353
29k
Adopting Sorbet at Scale
ufuk
71
8.8k
Git: the NoSQL Database
bkeepers
PRO
423
64k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
325
21k
Speed Design
sergeychernyshev
9
270
Making Projects Easy
brettharned
111
5.7k
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