Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hooks時代の設計の話 #agrinoteinside

Hooks時代の設計の話 #agrinoteinside

ウォーターセル株式会社の社内勉強会 https://water-cell.connpass.com/event/178648/ で発表したものです。

YouTube Liveアーカイブはこちら
https://youtu.be/ZLUie-ndKgw

Yukiya Nakagawa

June 25, 2020
Tweet

More Decks by Yukiya Nakagawa

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  7. React Component
    as a
    Fat Controller
    const FatController = () => {
    return (


    {hoge}
    {fuga}
    {piyo}


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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. Better
    const FatController = () => {
    return (


    {hoge}
    {fuga}
    {piyo}


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

    View Slide

  14. React Hooksͱڽू౓ɾ݁߹౓
    14

    View Slide

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

    View Slide

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

    View Slide

  17. More Better
    const FatController = () => {
    return (


    {hoge}
    {fuga}
    {piyo}


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

    View Slide

  18. 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

    View Slide

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

    View Slide

  20. ϑοΫ͸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

    View Slide

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

    View Slide

  22. ঢ়ଶΛѻ͏ϑοΫ
    ʢ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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  32. 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

    View Slide

  33. ͓͠·͍

    View Slide