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

propsのバケツリレー対策でGlobal_Stateを使うその前に

taro28
January 18, 2023

 propsのバケツリレー対策でGlobal_Stateを使うその前に

こちらのイベントで使用した登壇資料です!
https://thecoo.connpass.com/event/269188/

taro28

January 18, 2023
Tweet

More Decks by taro28

Other Decks in Technology

Transcript

  1. propsのバケツリレー対策で Global Stateを使うその前に… フロントエンドLT新年会 2023.1.18 taro(@taroro_tarotaro)

  2. 自己紹介 • taro( @taroro_tarotaro) • シェルフィー株式会社で建設SaaSを作ってます!(2020.11〜) • React, TypeScript, Server

    Side Kotlin ※Reactしか触ったことがないため、Reactをベースとした話になります🙏
  3. はじめに

  4. はじめに 昨今よく言われるReactのstateの分類 1. Server Data Cache 2. Global State: 1を除くページをまたいで保持し続ける必要のあるstate

    3. Local State: ページをまたいで保持する必要のないstate https://zenn.dev/yoshiko/articles/607ec0c9b0408d
  5. はじめに 昨今よく言われるReactのstateの分類 1. Server Data Cache ◦ TanStack Query, swr,

    etc. 2. Global State: 1を除くページをまたいで保持し続ける必要のあるstate ◦ useContext, Recoil, Jotai, Redux, Zustand, etc. 3. Local State: ページをまたいで保持する必要のないstate ◦ useState, etc.
  6. はじめに 昨今よく言われるReactのstateの分類 1. Server Data Cache ◦ TanStack Query, swr,

    etc. 2. Global State: 1を除くページをまたいで保持し続ける必要のあるstate ◦ useContext, Recoil, Jotai, Redux, Zustand, etc. 3. Local State: ページをまたいで保持する必要のないstate ◦ useState, etc. 💡Local Stateを実装的都合でGlobal Stateの管理手法を使う時の話
  7. はじめに Local Stateを実装的都合でGlobal Stateの手段で管理する時の話 • どんなケースか • その場合のむずかしさ • ケース別にLocal

    Stateでうまくやる方法 ※変更頻度が多く複数人で触るようなComponentを前提としています🙇
  8. 実装的にGlobal Stateで 管理したくなるケース

  9. 実装的にGlobal Stateで管理したくなるケース • 子、孫Component間でstateを共有したい • propsのバケツリレー(props drilling)を避けたい • 子Component内のstateを親Componentから制御したい など

    →Global Stateで管理してもよいがむずかしさがある
  10. Global Stateで管理する時の むずかしさ

  11. Global Stateで管理する時のむずかしさ • スコープが広がる ◦ まぁGlobalだからね(Atoms系だと違うかも) • データフローが見えづらくなる ◦ 子Componentのpropから消えるため

    • ライフタイムが伸びる ◦ これの考慮が結構忘れがち ◦ クリーンアップ忘れて変更前のstateがチラっと見えちゃう🫣
  12. Global Stateで管理する時のむずかしさ • スコープが広がる ◦ まぁGlobalだからね(Atoms系だと違うかも) • データフローが見えづらくなる ◦ 子Componentのpropから消えるため

    • ライフタイムが伸びる ◦ これの考慮が結構忘れがち ◦ クリーンアップ忘れて変更前のstateがチラっと見えちゃう🫣 →影響範囲の把握コストが増える
  13. Global Stateで管理する時のむずかしさ • スコープが広がる ◦ まぁGlobalだからね(Atoms系だと違うかも) • データフローが見えづらくなる ◦ 子Componentのpropから消えるため

    • ライフタイムが伸びる ◦ これの考慮が結構忘れがち ◦ クリーンアップ忘れて変更前のstateがチラっと見えちゃう🫣 →影響範囲の把握コストが増える →僕はLocal Stateでがんばる派でその方法を紹介していく
  14. Local Stateで うまくやる方法

  15. Local Stateでうまくやる方法 実装的にGlobal Stateで管理したくなるケース • 子、孫Component間でstateを共有したい • propsのバケツリレー(props drilling)を避けたい •

    子Component内のstateを親Componentから制御したい
  16. Local Stateでうまくやる方法 実装的にGlobal Stateで管理したくなるケース • 子、孫Component間でstateを共有したい • propsのバケツリレー(props drilling)を避けたい •

    子Component内のstateを親Componentから制御したい
  17. Local Stateでうまくやる方法 ①まずは基本のLifting State Up 「当たり前だろ!」と言われるかもしれないが、 親に持ち上げてstateの持ち方を変えるだけで意外と解決したりする。

  18. Local Stateでうまくやる方法 ①まずは基本のLifting State Up 「当たり前だろ!」と言われるかもしれないが、 親に持ち上げてstateの持ち方を変えるだけで意外と解決したりする。 →「いやいやそうするとpropsをバケツリレーしないといけないんよ…」

  19. Local Stateでうまくやる方法 実装的にGlobal Stateで管理したくなるケース • 子、孫Component間でstateを共有したい • propsのバケツリレー(props drilling)を避けたい •

    子Component内のstateを親Componentから制御したい
  20. Local Stateでうまくやる方法 ②propを渡すこと自体はそんなに悪いことではない • むしろ依存関係があるから、依存関係がわかるように書いている • ただ個数が多かったり、バケツリレーを繰り返してたら疑うのは大切

  21. Local Stateでうまくやる方法 ③そもそもそんなにComponentをネストさせる必要があるのか?

  22. Local Stateでうまくやる方法 ③そもそもそんなにComponentをネストさせる必要があるのか? ※変更頻度が多く複数人で触るようなComponentが前提 • ロジックやstateはCustom Hookで責任ごとに分ける • 機能に依存しない小さな汎用Componentを作る •

    機能のComponentはそれらを組み合わせ機能内でのネストは最小限にする ◦ Viewの全体像がわかりやすい ◦ 不要なインターフェースが生まれず、柔軟性が保たれる
  23. Local Stateでうまくやる方法 ④Composition: childrenを使う propが減って変更に強くなり、また状態の依存関係がわかりやすくなる

  24. Local Stateでうまくやる方法 ⑤Composition: render props使う 親Componentの肥大化を防ぎたい時におすすめ(初見の難しさが少し上がる)

  25. Local Stateでうまくやる方法 実装的にGlobal Stateで管理したくなるケース • 子、孫Component間でstateを共有したい • propsのバケツリレー(props drilling)を避けたい •

    子Component内のstateを親Componentから制御したい
  26. Local Stateでうまくやる方法 ①やっぱりまずは基本のLifting State Up そもそも親から制御したいという要求の時点で危険な臭いがする… (ただ実際やりたいケースもあるので紹介していく)

  27. Local Stateでうまくやる方法 ⑥Component自体を初期化する • 親から制御したい多くのケースはstateの初期化 • Componentに動的なkeyを渡すとkeyごとにComponentを作り直してくれる

  28. Local Stateでうまくやる方法 ⑥Component自体を初期化する • 親から制御したい多くのケースはstateの初期化 • Componentに動的なkeyを渡すとkeyごとにComponentを作り直してくれる 「〇〇から◆◆に変わったら、△△する」のではなく、 「〇〇の時は♡♡、◆◆の時は△△する」と考えるのが大切(宣言的)

  29. Local Stateでうまくやる方法 ⑥Component自体を初期化する • 親から制御したい多くのケースはstateの初期化 • Componentに動的なkeyを渡すとkeyごとにComponentを作り直してくれる →「いやいやComponentをUnmountさせるのはUX的にやりたくない」 →「特定のstateだけ初期化(制御)したい」

  30. Local Stateでうまくやる方法 ⑦propとstateの値からsetStateする

  31. Local Stateでうまくやる方法 ⑦propとstateの値からsetStateする • 状態の性質として正しい姿を宣言する • useEffectは不要( 使うと前のstateで一度DOMにcommitされてしまう) 「〇〇から◆◆に変わったら、△△する」のではなく、 「〇〇の時は♡♡、◆◆の時は△△する」と考えるのが大切(宣言的)

  32. Local Stateでうまくやる方法 ⑧前レンダリング時のstateやpropの値を保持するstateを使う • これは正直あんまりやりたくない • ここまでくるともしかしたらGlobal Stateを使う方がシンプルかもしれない

  33. Local Stateでうまくやる方法 ①まずは基本のLifting State Up ②propを渡すこと自体はそんなに悪いことではない ③そもそもそんなにComponentをネストさせる必要があるのか考える ④Composition: childrenを使う ⑤Composition:

    render propsを使う ⑥Component自体を初期化する ⑦propとstateの値からsetStateする ⑧前レンダリング時のstateやpropの値を保持するstateを使う
  34. まとめ

  35. まとめ • 実装都合でGlobal Stateを使う時はむずかしさの考慮を忘れずに ◦ 制約がない・自由の裏には何があるのか • 設計を見直すとLocal Stateでも意外といける ◦

    Hackではなく全て公式ドキュメントの方法
  36. 積極採用中です!!
 採用情報はこちら! https://hello.shelfy.co.jp