useEffect完全ガイドを読んでみる
useEffectへの理解が浅い気がする。ということで、読んでみる。
componentDidMountをuseEffectで再現する方法は?
読んでみて気になったこと
覚えて欲しいことは、effects と componentDidMount や他のライフサイクルメソッドのメンタルモデルは別であることです。
そのメンタルモデルはライフサイクルイベントに反応することではなく props や state の変化を DOM にシンクロさせる、という方に近いです。
なるほど。propsやstateの変化に対して、DOMを非同期で書き換えるとかに向いているということかな。
renderについて深く理解するために、後で https://overreacted.io/react-as-a-ui-runtime/ を読んでみよう
流れに逆らう
を読んでみてわかったこと
useEffectが参照するstateや、propsはあくまでそのuseEffectが発火するときの断面のstate, propsなので、最新の値を見る必要がある場合はmutable refを使用する
ここらへんはあまり意識したことなかったなー
では Cleanup はどうでしょう?
読んで気づいたこと
前のエフェクトは新しい props で re-render されてから cleanup されます
re-render直前にcleanupされるものだと思っていた。
気にするケースがあるかどうかわからないが、知っておいて損はなさそう
React に依存関係の嘘をついてはならない
読んでみてわかったこと。
deps を指定する場合、 コンポーネント内の値がありエフェクトでも使われてる場合は、全て記述してください。 それはコンポーネント内の props, state, そして関数も含みます。
とあるので、追加してみるが、追加すればするほど、cleanup関数が実行されることにもなるので、
よく変わる値をそもそも必要としないエフェクトにコードを書き換える
というテクニックを覚えることが必要そう
で、「そのことが自律的なエフェクトを作る」に書いてある。
読んでみると、useStateのsetXX関数を関数型の更新の形( setXX(c => c + 1)
)にしてあげれば良い。そうすると、現在のXXの値に依存しなくなると
ただ、関数型の更新の形はstateの単純な更新にしか使えない。propsとstate、別々のstateの掛け合わせの場合は、useReducer
に置き換えることを検討してみると良い
reducer
はコンポーネント内で起こったアクションと、そのレスポンスに応じてstateがアップデートされる関係性を分離してくれます。
ふむふむ。reduxに近い感じという説明を前読んだが、業務ではあんまり使ってないな、、
エフェクト内に関数を入れる
eslint-plugin-react-hooks
プラグインを入れることにより、抜けている依存関係をチェックしてくれる。素敵。
でも、この関数はエフェクト内に入れられない
読んだ
依存する関数はuseEffect内に入れるのが基本だが、複数のuseEffect内で呼び出される関係で、どうしてもuseEffect外に定義しないと行けない場合がある。
そんな場合の対応は2つ
- 関数をコンポーネント外にホイスティングして自由にエフェクト内で使う(ただし、関数コンポーネント内の値は使えない)
- useCallbackを使用する
1つ目は制約もあるし、2つ目の使い勝手が良さそう
ハードルをあげる
読む
Suspense が今後データフェッチングケースをハンドリングしていくにつれ、useEffect は表舞台からフェードアウトして、本当に props や state を何かしらの副作用にシンクロしたい時だけに使われると思います
なるほどー
データフェッチングでuseEffect使うのは、過渡期的対応なのかー
今度、Suspense使ってみよう