Slide 1

Slide 1 text

redux-pluto 2018/04/19 @ Folio Meetup # Scramble! #1

Slide 2

Slide 2 text

Twitter: @yosuke_furukawa Github: yosuke-furukawa

Slide 3

Slide 3 text

redux-pluto • ϦΫϧʔτςΫϊϩδʔζࣾͰ։ൃதͷϘΠϥʔϓ Ϩʔτ • େن໛։ൃ޲͚ɺϕετϓϥΫςΟεΛूΊͨ΋ ͷ • ͪͳΈʹ·ͩ։ൃதͳͷͰࠓ೔͸ϦϙδτϦ͸ެ ։Ͱ͖ͳ͍Ͱ͢ɺӶҙקΊதͰ͢ɻ
 ͍͢·ͤΜɺɺɺ

Slide 4

Slide 4 text

redux-pluto • ϦΫϧʔτςΫϊϩδʔζࣾͰ։ൃதͷϘΠϥʔϓ Ϩʔτ • େن໛։ൃ޲͚ɺϕετϓϥΫςΟεΛूΊͨ΋ ͷ • ͪͳΈʹ·ͩ։ൃதͳͷͰࠓ೔͸ϦϙδτϦ͸ެ ։Ͱ͖ͳ͍Ͱ͢ɺӶҙקΊதͰ͢ɻ
 ͍͢·ͤΜɺɺɺ ࠓ೔͸͜ͷϕετϓϥΫςΟεΛ νϥݟͤ

Slide 5

Slide 5 text

ϕετϓϥΫςΟε ΞʔΩςΫνϟฤ

Slide 6

Slide 6 text

ϕετϓϥΫςΟε 1
 ඇಉظσʔλϩʔυ

Slide 7

Slide 7 text

ඇಉظσʔλϩʔυ • redux-async-loader • SSRͰ΋CSRͰ΋ಈ͘σʔλFetchؔ਺Λఏڙ ͯ͘͠ΕΔ • σʔλFetchத͸ReactͷrenderΛ͠ͳ͍࡞Γ

Slide 8

Slide 8 text

ඇಉظσʔλϩʔυ • 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 { // ... });

Slide 9

Slide 9 text

ඇಉظσʔλϩʔυ • ଞͷ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

Slide 10

Slide 10 text

ඇಉظσʔλϩʔυ • Ͳͷํ๏Ͱ΋͍͍ͩͨಉ͕ͩ͡ɺredux-async- loader͸Ͳ͜ͷίϯϙʔωϯτ͔ΒͰ΋ඇಉظ σʔλϩʔυͰ͖Δɻ • Next.js, Nuxt.js ͷ΋ͷ͸RootͰͷΈൃՐՄೳ • େن໛։ൃͩͱ్தͷComponent͔ΒͰ΋ඇಉ ظϩʔυͰ͖Δํ͕خ͍͜͠ͱ΋ɻ

Slide 11

Slide 11 text

ϕετϓϥΫςΟε 2
 reduxϑϩʔ੍ޚ

Slide 12

Slide 12 text

reduxϑϩʔ੍ޚ • redux-effects-steps
 https://github.com/recruit-tech/redux-effects-steps • redux-thunk΍sagaɺObservableͱ͍͏खஈ͕͋Δ ͕ͦΕΒ͸࢖ͬͯͳ͍ɻ • ϑϩʔ੍ޚͰෳࡶͳॲཧΛॻ͚ΔΑ͏ʹͨ͘͠ͳ͍ • ෳࡶʹͳͬͯ͠·͏ͷͰ͋Ε͹middlewareʹಀ͕͢

Slide 13

Slide 13 text

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] ); }

Slide 14

Slide 14 text

reduxϑϩʔ੍ޚ • ଞͷOSSࣄྫ • redux-thunk • redux-saga • redux-observable

Slide 15

Slide 15 text

reduxϑϩʔ੍ޚ • redux-thunk͸ԿͰ΋Ͱ͖͗͢ΔɺActionΛॻ͘ॴͰࡉ͔͍ॲ ཧ͕ॻ͚Δͷ͸΍Γա͗ײ͋Δɻ͕ͦ͜Ԛ͘ͳΓͦ͏ɻ • redux-saga͸sagaͱ͍͏ϨΠϠͰόοΫάϥ΢ϯυϓϩηε తʹԿͰ΋΍Δɻ͜͜·Ͱͷॲཧ͕ඞཁʹͳͬͨέʔε͕গͳ ͍ɺΑ͋͘Δͷ͸ϦΫΤετΛൃՐͯͦ͠Ε͕੒ޭ͔ࣦͨ͠ഊ ͔ͨ͠ఔ౓ɺͦΕ͚ͩͰsaga͸ΦʔόʔΩϧײ • observable͸RxJSͰྲྀΕΛ੍ޚ͢Δͱ͍͏΋ͷ͕ͩɺͦ͜· Ͱͷྲྀྔ੍ݶ͕ඞཁʹͳͬͨ͜ͱ͕ͳ͍

Slide 16

Slide 16 text

ϕετϓϥΫςΟε 3
 ducks

Slide 17

Slide 17 text

ducks • https://github.com/erikras/ducks-modular- redux • reducer, actions, action creatorͱ͍͏ػೳͰ ෼͚ΔͷͰ͸ͳ͘ɺUserɺArticleͱ͍ͬͨΑ ͏ͳϦιʔεͷѻ͍Ͱ̍ͭͷϑΝΠϧʹ͢Δ

Slide 18

Slide 18 text

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);

Slide 19

Slide 19 text

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) => {…}))

Slide 20

Slide 20 text

ducks • actions, action creator, reducer ͚ͩͰ͸ͳ͘ɺselector· Ͱதʹ࣋ͭɻ • ϑΝΠϧ͕େ͖͘ͳΓͦ͏ͳ࣌͸ϑΥϧμʹͯ͠ϑΝΠϧ ෼ׂ͢Δͷ΋༗Γɻ͜ͷล͸޷͖ʹ • re-ducksͱ͍͏΋ͷ΋͋Δ͕ɺ͜ΕͱͷϋΠϒϦουײɻ • ཁ͸΍Γ͍ͨͷ͸Ϧιʔε࣠Ͱ·ͱΊΔํ͕ػೳ࣠Ͱ·ͱ ΊΔΑΓ΋ॻ͖΍͘͢ɺݟ΍͔ͬͨ͢ɻ

Slide 21

Slide 21 text

ϕετϓϥΫςΟε 4
 APIఆٛ

Slide 22

Slide 22 text

APIఆٛ • agreed https://github.com/recruit-tech/ agreed • Consumer Driven ContractΛ࣮ફ • ϑϩϯτΤϯυ͕த৺ʹͳͬͯ։ൃΛ͢͢Ί Δ࢓૊Έʹͳ͍ͬͯΔɻ

Slide 23

Slide 23 text

APIఆٛ • agreedͰAPIͷmockΛઌʹ࡞੒ • mockΛ࡞ΓऴΘͬͨΒAPI࡞੒ऀ(Server Side)ʹagreed-uiͰཁٻΛڞ༗ɻ • API͕ߏஙͰ͖͖ͯͨΒagreed-clientͰςετ έʔεͱ࣮ͯ͠ߦ͞ΕΔɻ

Slide 24

Slide 24 text

APIఆٛ

Slide 25

Slide 25 text

APIఆٛ • ଞOSSࣄྫ • Swagger • Pact

Slide 26

Slide 26 text

APIఆٛ • Swagger͸APIͷ࢓༷ఆٛͰ͋ͬͯAPIͷཁٻ Ͱ͸ͳ͍ɻ͋͘·ͰυΩϡϝϯτɺmock΋࡞ ΕΔ͕࡞Γ΍͘͢͸ͳͦ͞͏ɻ • Pact͸clientͷςετσʔλ͔Βserverͷ νΣοΫΛ͢ΔͨΊͷσʔλΛࣗಈੜ੒͢Δ ࢓૊Έɻςετσʔλ͕ඞཁͳͷ͸ਏ͍ɻɻ

Slide 27

Slide 27 text

ϕετϓϥΫςΟε UIฤ

Slide 28

Slide 28 text

ϕετϓϥΫςΟε ϑΥʔϜ

Slide 29

Slide 29 text

ϑΥʔϜฤ • 2017೥ͷformʹ͍ͭͯ • https://speakerdeck.com/yosuke_furukawa/ 2017nian-falseformfalsehua

Slide 30

Slide 30 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY +BWB4DSJQUͷϝϞϦ

Slide 31

Slide 31 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY +BWB4DSJQUͷϝϞϦ 6ODPOUSPMMFE 'PSN $POUSPMMFE 'PSN

Slide 32

Slide 32 text

Uncontrolled vs Controlled • DOMͷ஋Λ௚઀࢖͏ (Uncontrolled) • DOM͔Βऔ͖ͬͯͨ஋ΛJSͷϝϞϦʹೖΕ ͯɺεφοϓγϣοτͱͯ͠࢖͏ (Controlled)

Slide 33

Slide 33 text

Uncontrolled form // React ͩͱ͜͏ class NameForm extends React.Component { // … handleSubmit(event) { alert('A name was submitted: ' + this.input.value); event.preventDefault(); } render() { return ( Name: this.input = input} /> ); } }

Slide 34

Slide 34 text

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 ( Name: ); } }

Slide 35

Slide 35 text

Uncontrolled vs Controlled • Controlled ͳํ͸ ͜͜Ͱ͸ React ͷ state ͱ ͯ͠؅ཧ͢Δ • Uncontrolled ͳํ͸DOMʹ͚ͩ؅ཧͤ͞Δ

Slide 36

Slide 36 text

Uncontrolled vs Controlled • Facebook ͕ਪ঑ͯ͠Δͷ͸ Controlled Ұ୒ • React ͷ v-dom ߋ৽ͷλΠϛϯάͱ΋߹Θͤͯ React ͕࠷దԽͨ͠ํ๏ͰDOMʹ൓өͤ͞Δ͜ͱ ͕Ͱ͖Δ • ͪΐͬͱڽͬͨformΛ࡞Ε͹େମControlledͰ࣮ ૷͢Δඞཁ͕ग़ͯ͘Δɻ

Slide 37

Slide 37 text

Uncontrolled vs Controlled • jQuery UI Έ͍ͨͳϥΠϒϥϦ͸େମ Uncontrolled ͳํ๏Ͱ΍ͬͯΔ͜ͱ͕ଟ͍ʢؾ ͕͢Δʣ • طଘͷࢿ࢈͕jQueryʹ͋ͬͯͦΕ͕ Uncontrolled ͳํ๏Ͱ࣮ݱ͞ΕͯΔͳΒ࢖͏ͷ ΋ྑ͍͕ɺجຊ͸ Controlled Ͱྑ͍ؾ͕͢Δɻɹ

Slide 38

Slide 38 text

Uncontrolled vs Controlled • https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/

Slide 39

Slide 39 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY +BWB4DSJQUͷϝϞϦ 6ODPOUSPMMFE 'PSN ΋͏๨Εͯ΋ྑ͍͔΋ $POUSPMMFE 'PSN ͓ͬͪ͜͢͢Ί

Slide 40

Slide 40 text

Ͱ΋ 2017 ೥ݱࡏ͸ state ͕ ෳ਺͋Δ

Slide 41

Slide 41 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%#

Slide 42

Slide 42 text

Ͳ͜ʹ஋Λอଘ͢Δͷ͕ਖ਼͠ ͍ͷ͔ʁ

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

6TF3FBDUGPSFQIFNFSBMTUBUFUIBUEPFTO`UNBUUFSUPUIF BQQHMPCBMMZ

Slide 45

Slide 45 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# &QIFNFSBM &UFSOBM 'PSFWFS

Slide 46

Slide 46 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# Ұ࣌తͳGPSNͷ஋ ͳΒ͜͜ʹ HMPCBMͳTUBUFͳΒ ͜͜ʹ

Slide 47

Slide 47 text

Ͱ΋΍ͬͯΈΔͱ

Slide 48

Slide 48 text

React ͷ state ͱ Redux ͷ state Ͱ form ͔ͩΒͱ͍ͬͯ ෼͚Δͷ໘౗

Slide 49

Slide 49 text

ࠓ͸

Slide 50

Slide 50 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# ͳΜ͔ύϑΥʔϚϯεͷϘ τϧωοΫ͕͋ͬͨΒ͜͜ جຊ͜͜

Slide 51

Slide 51 text

twitter Lite ͷߏ੒

Slide 52

Slide 52 text

ࠓͷ form ͷ஋Λ؅ཧ͢Δ৔ॴ %0. 3FBDU 3FEVY -PDBMTUPSBHF DPPLJF *OEFYFE%# UXJUUFSͷGPSNͷ৘ใ͸ Ұ୴͜͜ͰCV⒎FS ਺จࣈهड़ͨ͠Β SFEVDFSʹߦ͘

Slide 53

Slide 53 text

͋Δఔ౓ form ͷ৘ใ͸ React ͰͨΊͯɺ਺จࣈೖΕ ͨΒ Redux ʹ flush ͤ͞Δɻ

Slide 54

Slide 54 text

ϕετϓϥΫςΟε Ծ૝εΫϩʔϧ

Slide 55

Slide 55 text

Ծ૝εΫϩʔϧ • େલఏ: • DOMͷཁૉ͕૿͑Ε͹૿͑Δ΄Ͳϖʔδ͸ ॏ͘ͳΔ͠ɺΧΫͭ͘ • ϒϥ΢β্ͷϝϞϦ͕େ͖͘ͳΔ • ݟ͑ͯͳ͍ॴ͸DOMʹදࣔ͠ͳ͍͍ͯ͘

Slide 56

Slide 56 text

Ծ૝εΫϩʔϧ • ݟ͑ͯΔͱ͜Ζ͚ͩDOMͱͯ͠දࣔ͢Δ • react-virtualized Λ࢖͏ %0.ͱͯ͠ දࣔ %0.͔Β ͸ഁغ

Slide 57

Slide 57 text

ϕετϓϥΫςΟε ແݶεΫϩʔϧ

Slide 58

Slide 58 text

ແݶεΫϩʔϧ • େલఏ: • Ϣʔβʔͷճ༡࣌ؒΛ૿΍͍ͨ͠ɻ
 ݕࡧͨ͠Β2ϖʔδ໨Ҏ߱΋ͪΌΜͱݟ͍ͤͨɻ • ͪ·ͪ·࣍΁ͱ͔ϖʔδͷϦϯΫΛԡ͞ͳ͖Ό͍͚ͳ͍ͷ͸໘ ౗ʢಛʹϞόΠϧʣ • ͔ͱݴͬͯSEO͸ઈରʢεΫϩʔϧ͢Δͷ͸Ϣʔβʔ͚ͩͰ Google Crawler͸εΫϩʔϧΠϕϯτ·ͰൃՐͯ͘͠Εͳ͍ʣ

Slide 59

Slide 59 text

ແݶεΫϩʔϧ • ແݶεΫϩʔϧ x ϖʔδωʔγϣϯ • Ϣʔβʔ΋Ϋϩʔϥʔ΋
 ྆ํϑϨϯυϦʔʹɻ ໭Δ 1 2 3 4 5 6 7 8 9 10 ࣍΁

Slide 60

Slide 60 text

όουϊ΢ϋ΢ ΍ͬͯΈ͚ͨͲμϝͩͬͨฤ

Slide 61

Slide 61 text

ϋϚΓ·ͬͨ͘ babel plugins

Slide 62

Slide 62 text

babel-plugin-transform-react- inline-elementsͰIEͷࢮ

Slide 63

Slide 63 text

transform-react-constant- elementsͰbabelόάΛ౿Ή

Slide 64

Slide 64 text

transform-react-constant- elementsͰbabelόάΛ౿Ή • ൵C

Slide 65

Slide 65 text

Α͘Α͘ߟ͑Δͱͨ͘͞Μ͋Δ • fetchrͷෆ۩߹Λ౿Μͩ
 ʢओʹηΩϡϦςΟ໘ʣ • React v15ͰϝϞϦʔϦʔΫʹ೰·͞ΕΔɺv16Ͱղফ • react-router v4ະରԠ • etc…

Slide 66

Slide 66 text

Α͘Α͘ߟ͑Δͱͨ͘͞Μ͋Δ • fetchrͷෆ۩߹Λ౿Μͩ
 ʢओʹηΩϡϦςΟ໘ʣ • React v15ͰϝϞϦʔϦʔΫʹ೰·͞ΕΔɺv16Ͱղফ • react-router v4ະରԠ • etc… ܾͯ͠ॱ෩Ͱ͸ͳ͍͕ɺԶΒ͸΍ͬ ͍ͯͧ͘ʂʂʂʂ

Slide 67

Slide 67 text

·ͱΊ • ϕετϓϥΫςΟεʢΞʔΩςΫνϟฤʣ • ඇಉظϩʔυ • reduxϑϩʔ੍ޚ • ducks • APIఆٛ • ϕετϓϥΫςΟε(UIฤ) • ϑΥʔϜ • Ծ૝εΫϩʔϧ • ແݶεΫϩʔϧ • όουϓϥΫςΟε • babel plugin…, onlyUpdateForPropTypes…, etc