Closed9

useEffect完全ガイドを読んでみる

mongolyymongolyy

componentDidMountをuseEffectで再現する方法は?

読んでみて気になったこと

覚えて欲しいことは、effects と componentDidMount や他のライフサイクルメソッドのメンタルモデルは別であることです。
そのメンタルモデルはライフサイクルイベントに反応することではなく props や state の変化を DOM にシンクロさせる、という方に近いです。

なるほど。propsやstateの変化に対して、DOMを非同期で書き換えるとかに向いているということかな。

mongolyymongolyy

流れに逆らう

を読んでみてわかったこと
useEffectが参照するstateや、propsはあくまでそのuseEffectが発火するときの断面のstate, propsなので、最新の値を見る必要がある場合はmutable refを使用する
ここらへんはあまり意識したことなかったなー

では Cleanup はどうでしょう?

読んで気づいたこと

前のエフェクトは新しい props で re-render されてから cleanup されます

re-render直前にcleanupされるものだと思っていた。
気にするケースがあるかどうかわからないが、知っておいて損はなさそう

mongolyymongolyy

React に依存関係の嘘をついてはならない

読んでみてわかったこと。

deps を指定する場合、 コンポーネント内の値がありエフェクトでも使われてる場合は、全て記述してください。 それはコンポーネント内の props, state, そして関数も含みます。

とあるので、追加してみるが、追加すればするほど、cleanup関数が実行されることにもなるので、

よく変わる値をそもそも必要としないエフェクトにコードを書き換える

というテクニックを覚えることが必要そう
で、「そのことが自律的なエフェクトを作る」に書いてある。
読んでみると、useStateのsetXX関数を関数型の更新の形( setXX(c => c + 1) )にしてあげれば良い。そうすると、現在のXXの値に依存しなくなると

mongolyymongolyy

ただ、関数型の更新の形はstateの単純な更新にしか使えない。propsとstate、別々のstateの掛け合わせの場合は、useReducerに置き換えることを検討してみると良い

reducerはコンポーネント内で起こったアクションと、そのレスポンスに応じてstateがアップデートされる関係性を分離してくれます。

ふむふむ。reduxに近い感じという説明を前読んだが、業務ではあんまり使ってないな、、

mongolyymongolyy

エフェクト内に関数を入れる

eslint-plugin-react-hooks プラグインを入れることにより、抜けている依存関係をチェックしてくれる。素敵。

mongolyymongolyy

でも、この関数はエフェクト内に入れられない

読んだ

依存する関数はuseEffect内に入れるのが基本だが、複数のuseEffect内で呼び出される関係で、どうしてもuseEffect外に定義しないと行けない場合がある。
そんな場合の対応は2つ

  • 関数をコンポーネント外にホイスティングして自由にエフェクト内で使う(ただし、関数コンポーネント内の値は使えない)
  • useCallbackを使用する

1つ目は制約もあるし、2つ目の使い勝手が良さそう

mongolyymongolyy

ハードルをあげる

読む

Suspense が今後データフェッチングケースをハンドリングしていくにつれ、useEffect は表舞台からフェードアウトして、本当に props や state を何かしらの副作用にシンクロしたい時だけに使われると思います

なるほどー
データフェッチングでuseEffect使うのは、過渡期的対応なのかー
今度、Suspense使ってみよう

このスクラップは2021/06/22にクローズされました