Slide 1

Slide 1 text

Hooks࣌୅ͷઃܭͷ࿩ React Hooksษڧձ #6 2020.6.25 Yukiya Nakagawa a.k.a Nkzn 1

Slide 2

Slide 2 text

Yukiya Nakagawa ΢Υʔλʔηϧࣾһ൪߸3൪ ϞόΠϧΤϯδχΞ ٕज़ॻయWebΛReact.FCͱHooksͰ ϦϓϨΠεͨ͠ओ൜ 2

Slide 3

Slide 3 text

ΞδΣϯμ • ࠓճݴٴ͢Δʮઃܭʯ • Fat Controller͔Βߟ͑Δڽू౓ͱ݁߹౓ • React Hooksͱڽू౓ɾ݁߹౓ • ڽू౓ɾ݁߹౓ʹӨڹ͢ΔϑοΫɺ͠ͳ͍ϑοΫ • ڽू౓ɾ݁߹౓͕ѱ͘ͳΔϑοΫΛͲ͏ѻ͏͔ • StorybookΛ࢖͍͍ͨ৔߹͸΋͏Ұखؒ 3

Slide 4

Slide 4 text

ࠓճݴٴ͢Δʮઃܭʯ • ઃܭͱ͸ݱ࣮ੈքͷ՝୊Λղܾ͢ΔͨΊʹ1ͭ·ͨ͸ز͔ͭͷ؍఺͔ Βଥ౰ͳࢪࡦΛݕ౼ɾܾఆ͢Δ͜ͱʢཁग़యʣ • ϑΝΠϧ΍ϑΥϧμ΍Ҿ਺ͷ্खͳ੔ཧͷ࢓ํ͸ɺઃܭͰ͸ͳ͘ߏ଄ ͱݺ͹ΕΔ෼໺ • ͲΜͳ՝୊Λղܾ͢ΔͨΊʹɺͲΜͳ؍఺Ͱߏ଄ΛܾΊ͍͔ͯ͘ • React Hooks͕ੜΈग़͢ߏ଄͸ɺڽू౓ͱ݁߹౓ͷ՝୊Λղܾ͠΍͢ ͍ʢؾ͕͢ΔʣͷͰɺࠓճ͸ڽू౓ͱ݁߹౓ͷ࿩Λ͠·͢ 4

Slide 5

Slide 5 text

Fat Controller͔Βߟ͑Δ ڽू౓ͱ݁߹౓ 5

Slide 6

Slide 6 text

GUIϑϨʔϜϫʔΫͷӬԕͷ՝୊ • Fat Controller • UIͷݟͨ໨Λ௚઀ѻ͑ΔείʔϓʹɺશͯͷϩδοΫΛॻ͘ελΠϧ • Reactͷؔ਺ίϯϙʔωϯτͰ͍͏ͱɺreturnͷ্ 6

Slide 7

Slide 7 text

React Component as a Fat Controller const FatController = () => { return ( {hoge} {fuga} {piyo} ) }; ෳ਺ͷؔ৺ʹର͢Δॲཧ͕ ίϯϙʔωϯτʹϕλॻ͖ ͞Ε͍ͯΔঢ়ଶ ࠷ऴతʹදࣔ͢Δσʔλͷ؅ཧʢ6*ͷؔ৺ʣߦ ΫϦοΫΠϕϯτͷड͚औΓʢ6*ͷؔ৺ʣɿߦ ॳظԽ༻ͷ௨৴ʢ௨৴ͷؔ৺ʣߦ σʔλૹ৴༻ͷ௨৴ʢ௨৴ͷؔ৺ʣɿߦ +49͸6*ͷؔ৺ ௨৴݁ՌΛදࣔ༻σʔλʹՃ޻͢ΔʢՃ޻ͷؔ৺ʣɿߦ 7

Slide 8

Slide 8 text

Fat ControllerͷԿ͕ѱ͍ͷ͔ • WebϑϩϯτΤϯυͰ͋Ε͹ɺ΄ͱΜͲͷॲཧ͸େผͯ͠ʮ௨৴ʯ ʮՃ޻ʯʮදࣔ/Πϕϯτड෇(UI)ʯͷͲΕ͔ͷؔ৺Λ࣋ͭ͜ͱ͕ଟ͍ • Fat ControllerͰ͸͜ΕΒͷॲཧ͕Ұಉʹհ͢Δ • ࠷ॳʹ࣮૷ͨ࣌͠఺Ͱ͸ಈ͘͠ɺ࣮૷ऀͷهԱʹ࿈ଓੑ͕͋ΔݶΓ͸ ϝϯςͰ͖Δ ϏδωεϩδοΫΛؚΉ 8

Slide 9

Slide 9 text

— Yukiya Nakagawa (1987- ) “͔࣮͠͠૷ऀ͸هԱΛࣦ͏” 9

Slide 10

Slide 10 text

໰୊఺ɿڽू౓͕௿͘ɺ݁߹౓͕ߴ͍ • ਺ඦߦʹ౉Δ༷ʑͳ໨తΛ࣋ͬͨॲཧͷதͰɺվमର৅ͷػೳʹ֘౰͢Δ ߦΛݟ͚ͭΔ࡞ۀ͸ࠔ೉ΛۃΊΔʢڽू౓͕௿͍ʣ • ͋Δ1ߦΛमਖ਼ͨ͠৔߹ͷӨڹൣғΛ஫ҙਂ֬͘ೝ͠ͳ͚Ε͹͍͚ͳ͍ʢ݁ ߹౓͕ߴ͍ʣ • ಛఆͷ਺ेߦ͔ΒͳΔҰ෦ͷػೳ͚ͩΛଞͷίϯϙʔωϯτͰ΋࠶ར༻͠ ͍ͨͱࢥͬͨ৔߹ʹɺͲͷߦΛൈ͖ग़ͤ͹͍͍͔Θ͔Βͳ͍ɺ͋Δ͍͸ί ϐϖ͢Δ͔͠ͳ͍ʢ݁߹౓͕ߴ͍ʣ 10

Slide 11

Slide 11 text

ཧ૝͸͜Ε • ڽू౓͕ߴ͍ߏ଄ • ࣅͨ໨తͷॲཧ͕·ͱΊΒΕ͍ͯΔ • ݁߹౓͕௿͍ߏ଄ • ͋·Γؔ܎ͷͳ͍ॲཧಉ͕࢜ૄ݁߹Ͱ͋Δ 11

Slide 12

Slide 12 text

ڽू౓͕ߴͯ݁͘߹౓͕௿͍ߏ଄ͮ͘Γ • ࣅͨ໨తͷॲཧΛಉ͡ϑΝΠϧ΍ϑΥϧμʹ·ͱΊͯɺ࢖͏ͱ͖͸౎౓Πϯϙʔτ͢Δ • ʮ௨৴ʯʮՃ޻ʯʮදࣔ/Πϕϯτड෇ʯ͸͢΂ͯผͷ໨తͷͨΊʹಈ͍͍ͯΔͷͰ ผϑΝΠϧʹ͢ΔͱΑ͍ • ʮ͜ͷछྨͷॲཧͳΒ͍͍ͩͨ͜ͷϑΥϧμΛݟʹ͍͚͹͋Δͳʯ͕Ͱ͖Δͷ͸͍͍͜ͱ • ʮ͜ͷϑΝΠϧΛमਖ਼ͯ͠΋յΕΔͷ͸͜ͷϑΝΠϧͷॲཧ͚ͩͩͳʯ͕Ͱ͖Δͷ΋͍͍͜ͱ • ES Modules͕࣮૷͞Εͯຊ౰ʹΑ͔ͬͨ (6*ΞϓϦέʔγϣϯͷϑΝΠϧɾϑΥϧμ੔ཧ͸͜Ε͕Ͱ͖Ε͹͍͍ͩͨউར 12

Slide 13

Slide 13 text

Better const FatController = () => { return ( {hoge} {fuga} {piyo} ) }; UIҎ֎ͷॲཧͷৄࡉΛ ผϑΝΠϧʹ௥͍ग़͢ ڽू౓͸͔ͳΓ্͕ͬͨ ݁߹౓͸গ͠Լ͕͚ͬͨͩ Ͱ·ͩڧ͍ ࠷ऴతʹදࣔ͢Δσʔλͷ؅ཧʢ6*ͷؔ৺ʣߦ ΫϦοΫΠϕϯτͷड͚औΓʢ6*ͷؔ৺ʣɿߦ ॳظԽ༻ͷ௨৴ʢ௨৴ͷؔ৺ʣߦ ʢผϑΝΠϧͷϞδϡʔϧΛݺͼग़͚ͩ͢ʣ σʔλૹ৴༻ͷ௨৴ʢ௨৴ͷؔ৺ʣɿߦ ʢผϑΝΠϧͷϞδϡʔϧΛݺͼग़͚ͩ͢ʣ +49͸6*ͷؔ৺ ʢ௨৴ॲཧͷϞδϡʔϧ͔Βݺ͹Ε͍͚ͯͨͩͳͷͰফ໓ʣ 13

Slide 14

Slide 14 text

React Hooksͱڽू౓ɾ݁߹౓ 14

Slide 15

Slide 15 text

React.FCͷڽू౓ɾ݁߹౓͕ߴ͍ʁ௿͍ʁ • propsʹج͍ͮͨදࣔͷΈΛߦ͏ίϯϙʔωϯτʢ͍ΘΏΔPresentational Componentʣ͸ɺڽू౓͕ߴ͘ɺ݁߹౓͕௿͍ • ϑοΫΛ1ͭͰ΋࢖ͬͨίϯϙʔωϯτ͸ɺ݁߹౓͕গ্͕͠Δ • ωΨςΟϒͳ࿩Ͱ͸ͳ͘ɺࣗવͳ͜ͱͱͯ͠ • ڽू౓͕Լ͕Δ͔Ͳ͏͔͸৔߹ʹΑΔ • ϑοΫΛͨ͘͞Μॻ͘ͱɺͦΕͳΓʹڽू౓͕Լ͕ͬͨΓ݁߹౓্͕͕ͬͨΓ͢Δ • Fat Controller΁ͷಓ 15

Slide 16

Slide 16 text

ΧελϜϑοΫ͸ྑ͍ӨڹΛٴ΅͢ • ॲཧΛΧελϜϑοΫʹ·ͱΊΔͱɺؔ਺ίϯϙʔωϯτ͔Β௚઀ѻ ͏ϑοΫͷ਺͕ݮΔͷͰɺ݁߹౓͕Լ͕Δ • ΧελϜϑοΫΛద੾ͳཻ౓ʹ·ͱΊΔ͜ͱ͕Ͱ͖Ε͹ɺڽू౓্͕ ͕Δ 16

Slide 17

Slide 17 text

More Better const FatController = () => { return ( {hoge} {fuga} {piyo} ) }; UIʹؔ৺ͷ͋Δॲཧ͔͠ѻ Θͳ͍ΧελϜϑοΫʹ͢ ΂ͯΛ௥͍ग़͢ ࠷ऴతʹදࣔ͢Δσʔλͱߋ৽ํ๏ͷΈΛఏڙ͢Δ ΧελϜϑοΫͷݺͼग़͠ɿߦ ΫϦοΫΠϕϯτͷड͚औΓʢ6*ͷؔ৺ʣɿߦ +49͸6*ͷؔ৺ 17

Slide 18

Slide 18 text

Real World const Articles = () => { const { data, loading, error } = useArticlesService(); if (loading) { return } if (error) { return } if (!data?.articles) { return } return ( <> {props.articles.map(article => ( title: {article.title} summary: {article.summary} ))} > ); }; ݟͨ͘ͳ͍΋ͷ͸Ӆṭ͢Δ ΧελϜϑοΫͷத͸FatͰ ΋Α͍ʢFat Model͸OKʣ GraphQL + Apollo ClientΛ࢖͍ͬͯΔͱΧελϜϑοΫͷ୅Θ ΓʹuseQueryͰ΋ߦ͚ͨΓ͢Δ ʢ௨৴ͷӅṭ͕Ͱ͖͍ͯΔˍՃ޻ॲཧ͕ݮΔ܏޲ʹ͋ΔͨΊʣ 'BUʹͳΔཁҼΛ ΧελϜϑοΫʹด͡ࠐΊΔ 18

Slide 19

Slide 19 text

ڽू౓ɾ݁߹౓ʹ Өڹ͢ΔϑοΫɺ͠ͳ͍ϑοΫ 19

Slide 20

Slide 20 text

ϑοΫ͸10छྨ͔͠ͳ͍ • ͍ΖΜͳΧελϜϑοΫΛோΊ͍ͯΔͱ๨Εͦ͏ʹͳΔΜ͚ͩͲɺVirtual DOMͷࠩ෼ݕ ग़ॲཧΛ࢘Δreact-reconcilerʢௐ࿨Λ΋ͨΒ͢ऀʣͱ௚݁ͨ͠ʮຊ෺ͷʯϑοΫ͸10छྨ ͔͠ͳ͍ • ࣮͸masterΛݟʹߦ͘ͱɺConcurrent ModeͳͲͷབྷΈͰ15ݸʹ૿͍͑ͯΔ*1Μ͚ͩ Ͳɺͻͱ·ͣݟͳ͔ͬͨ͜ͱʹͯ͠ཉ͍͠ • ૿͑ͨ෼ʹڵຯ͕͋Δਓ͸Concurrent ModeͷυΩϡϝϯτ*2ΛಡΜͰ΄͍͠ 1. https://github.com/facebook/react/blob/30b47103d4354d9187dc0f1fb804855a5208ca9f/packages/react-reconciler/src/ReactFiberHooks.new.js#L110-L124 2. https://ja.reactjs.org/docs/concurrent-mode-patterns.html 20

Slide 21

Slide 21 text

ϑοΫ͸10छྨ͔͠ͳ͍ • υΩϡϝϯτ্͸ʮجຊͷϑοΫʯʮ௥ՃͷϑοΫʯͱ͍͏࢖༻ස౓ʁʹΑΔ෼ྨ͕ߦΘ Ε͍ͯΔ͚Ͳɺઃܭ্͸΋͏গ͠ผͷ੾ΓޱͰ෼ྨͯ͠ೝ͓͍ࣝͯͨ͠΄͏͕ྑ͍ 21

Slide 22

Slide 22 text

ঢ়ଶΛѻ͏ϑοΫ ʢ7%0.ߋ৽ͷى఺ʹͳΕΔͷ͸ࣄ্࣮͜Ε͚ͩʣ w VTF4UBUF w VTF3FEVDFS ঢ়ଶΛ఻೻͢ΔϑοΫ w VTF$POUFYU ෭࡞༻Λѻ͏ϑοΫ w VTF&⒎FDU w VTF-BZPVU&⒎FDU ϝϞԽΛѻ͏ϑοΫ w VTF$BMMCBDL w VTF.FNP खଓ͖తϓϩάϥϛϯάΛѻ͏ϑοΫ w VTF3FG w VTF*NQFSBUJWF)BOEMF ಈ࡞ʹӨڹ͠ͳ͍ϑοΫ w VTF%FCVH7BMVF 22

Slide 23

Slide 23 text

ڽू౓ɾ݁߹౓΁ͷӨڹ • Ͳ͜ͷ֊૚ͷίϯϙʔωϯτʹஔ͍ͯ΋ڽू౓ɾ݁߹౓ʹ΄΅Өڹ͠ͳ͍ • ϝϞԽΛѻ͏ϑοΫ • खଓ͖తϓϩάϥϛϯάΛѻ͏ϑοΫ • ಈ࡞ʹӨڹ͠ͳ͍ϑοΫ • ڽू౓ɾ݁߹౓ʹμΠϨΫτʹӨڹ͢Δ • ঢ়ଶΛѻ͏ϑοΫʢσʔλʹؔ৺͕͋Δʣ • ෭࡞༻Λѻ͏ϑοΫʢ෭࡞༻Ͱ֎քʹܨ͕Γ͕ͪʣ • ঢ়ଶΛ఻೻͢ΔϑοΫʢ֎ք͔ΒσʔλΛྲྀ͠ࠐΉʣ 23

Slide 24

Slide 24 text

஫ҙ͢΂͖΋ͷ͸3෼ྨ͚ͩ • ঢ়ଶΛѻ͏ϑοΫʢ㲈 useStateʣ • ෭࡞༻Λѻ͏ϑοΫʢ㲈 useEffectʣ • ঢ়ଶΛ఻೻͢ΔϑοΫʢ㲈 useContextʣ جຊͷϑοΫͩʜʜʂʁ 24

Slide 25

Slide 25 text

ڽू౓ɾ݁߹౓ʹӨڹ͕͋Δ ϑοΫΛͲ͏ѻ͏͔ 25

Slide 26

Slide 26 text

ڽू౓ɾ݁߹౓ʹӨڹ͕͋ΔϑοΫΛͲ͏ѻ͏͔ • Ͱ͖Δ্͚ͩҐͷίϯϙʔωϯτͰར༻ͨ͠΄͏͕Α͍ • Atomic DesignͰ͍͏ͱ͜ΖͷOrganisms͘Β͍ͷ৔ॴͰ࢖͏Α͏ʹҙࣝ͢ΔͱΑ͍ • Molecules΍AtomsͰ΋ɺίϯϙʔωϯτͷ֎ଆʹӨڹΛٴ΅͞ͳ͍΋ͷͳΒ͹OK • ֎քͱͷ઀ଓΛΧελϜϑοΫʹҰຊԽ͢Δ • Reactͷ֎ଆʢΠϯλʔωοτ΍Reduxʣͱ΍ΓͱΓ͢ΔॲཧΛΧελϜϑοΫʹ·ͱΊ Δͱɺίϯϙʔωϯτͱͷ݁߹౓Λ࠷௿ݶʹ཈͑Δ͜ͱ͕Ͱ͖Δ • ࣗ࡞ͷΧελϜϑοΫ͚ͩͰ͸ͳ͘ɺαʔυύʔςΟͷΧελϜϑοΫʢuseQuery, useSWR, useFetch, useSelectorͳͲͳͲʣΛ௚઀ίϯϙʔωϯτʹઃஔͯ͠΋Α͍ ϖΠϯ୯Ґ͘Β͍ʹͳΔΜ͡Όͳ͍͔ͳͱ 26

Slide 27

Slide 27 text

StorybookΛ࢖͍͍ͨ৔߹͸΋͏Ұखؒ 27

Slide 28

Slide 28 text

Storybook + React Hooks͋Δ͋Δ • ֎ք͕བྷΉίϯϙʔωϯτ͸StorybookͰಈ͔ͮ͠Β͍ • ೝূ͕ඞཁͳ௨৴Λ൐͏useEffect΍ΧελϜϑοΫ͕ઃஔ͞Ε͍ͯΔ ৔߹͕ಛʹਏ͍ • ֎քͱͷ݁߹౓Λθϩʹͨ͠ίϯϙʔωϯτ͚͕ͩଘࡏΛڐ͞ΕΔ • ྫ֎తʹͱͷີ݁߹͸ڐ͞ΕΔ 28

Slide 29

Slide 29 text

Presentational and Container Components • 2015೥ͷهࣄ͕ॳग़*1 • 2019೥ͷDan Abramov͸ʮίʔυϕʔε্͜ͷ෼཭Λߦ͏͜ͱ͕ࣗવͰ͋Ε͹ ศརʹ࢖͑Δ͚Ͳɺͦ͏Ͱͳ͍ͳΒ͜ͷ෼཭ํ๏ΛӏವΈʹ͢Δͷ͸΍Ίͨ΄͏ ͕͍͍ɻෳࡶͳϩδοΫΛ෼཭͍͚ͨͩ͠Ͱ͋Ε͹ɺϑοΫΛ࢖͑͹ίϯϙʔω ϯτΛΘ͟Θ͟෼཭͢Δඞཁ΋ͳ͍͔ΒͰ͢ʯͱݴ͍ͬͯΔ • େͯ͠ෳࡶͳϩδοΫ΋͍࣋ͬͯͳ͍ͷʹɺ೴ࢮͰContainerΛ੾Γग़͍ͯ͠Δϓ ϩδΣΫτΛ͔ͦ͜͜͠Ͱݟ͔͚ͯݏʹͳͬͨΒ͍͠ • ͱ͸͍͑༗ޮͳͱ͖͸༗ޮͳͷͰɺྫྷ੩ʹ࢖͍͖͍ͬͯͨ 1. https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 29

Slide 30

Slide 30 text

Presentational and Container Components 1SFTFOUBUJPOBM $PNQPOFOUT $POUBJOFS $PNQPOFOUT ༻్ ݟͨ໨Λఆٛ͢Δ ৼΔ෣͍Λఆٛ͢Δ 3FBDUͷ֎ଆΛ ஌Βͳ͍ ஌͍ͬͯΔ 4UPSZCPPLͰ දࣔͰ͖Δ දࣔͰ͖ͳ͍͜ͱ͕ଟ͍ 30

Slide 31

Slide 31 text

StorybookΛ࢖͍͍ͨ৔߹͸΋͏Ұखؒ • Container͸ʮReactͰ͸ͳ͍ੈքͱͷڥքʯͱͯ͠ಇ͘ • ֎քͱͷ૭ޱʹͳΔΧελϜϑοΫ͸Container Componentsʹઃஔ ͢ΔͱΑ͍ 31

Slide 32

Slide 32 text

Presentational and Container Components // src/components/articles.js export const ArticlesComponent = (props) => ( <> {props.articles.map(article => ( title: {article.title} summary: {article.summary} ))} > ); // src/containers/articles.js export const Articles = () => { const { data, loading, error } = useArticlesService(); useErrorHandler(error); if (loading) { return } if (!data?.articles) { return } return }; ContainerଆʹʢΧελϜʣ ϑοΫΛઃஔ͢Δ͜ͱͰɺ Presentationalଆ͔Β֎ք΁ ͷ݁߹౓ΛԼ͛Δ ֎քͱͷ΍ΓͱΓ͸ $POUBJOFSʹ೚ͤΔ ඇಉظঢ়ଶͷ؅ཧ΍ ΤϥʔϋϯυϦϯάΛͲ͜Ͱ΍Δ͔͸ ٞ࿦ͷ༨஍͕͋Γͦ͏ 1SFTFOUBUJPOBM͸ ݟͨ໨ͷఆٛʹઐ೦͢Δ 32

Slide 33

Slide 33 text

͓͠·͍