useEffectとuseLayoutEffect


関数構成部品


Reactを使用してプロジェクトを設計する場合は、クラス構成部品と関数構成部品を使用できます.従来はクラス素子を用いていたが,時間が経つにつれて関数型素子がよく用いられるようになった.これは、クラスでコンストラクション関数を使用してstateを初期化し、関数でusStateを使用するとコードの長さが減少し、読みやすさが向上するためです.クラスでのみ使用可能なライフサイクルも、Hookの出現に伴って解決されます.実際のメモリリソースでも関数型はあまり使用されません.
では、クラス部品を知る必要はありませんか?もちろん違います.従来のコードはクラスコードであり、プロジェクト設計中にStackOverflowに遭遇した場合、参照する資料の多くはクラスコードである.そして、等級型が分かれば、反応に関する新しい知識があれば、もっとわかりやすくなります.

useEffect/useLayoutEffect


写真ソース

useEffect



まず、userEffectは非同期で実行されます.すなわち,上から下にコードがあれば,上のコードの結果値を受け取る前に,次のコードを実行することができる.さらに、エレメントはレンダリングされ、これらのエレメントが塗装されるとuseEffectが実行されます.
ブラウザレンダリングプロセスを簡単に見て、HTMLをDOMツリーとCSS生成CSOMツリーに分けます.この2つのツリー情報を用いて,ブラウザ画面に本当に露出する必要があるノードの情報Render Treeを生成する.次に、リフローと再描画の手順を実行します.

生成されたDOMノードのレイアウト値(幅、高さ、位置など)が変更されたときに影響を受けるすべてのノード(親、子など)の値を再計算することで、レンダーツリーを再生成するプロセスをリフローと呼びます.Reflowプロシージャが終了した後、再描画されたレンダリングツリーを再描画することを再描画と呼びます.
通常、DOMを操作するたびにリフローと再描画が行われ、ブラウザのパフォーマンスが低下します.仮想DOMを用いた反応は,リフローを最小化し,ペンキを塗り直す利点を有する.
いずれにしてもrenderとpaintは、useEffectがpaintの後に実行されるため、DOMに影響を与えるコードがあれば再描画され、画面が点滅する.

useLayoutEffect



useLayoutEffectは同期して実行され、paintの前に実行されます.画面に描画する前に実行されるため、userLayoutEffectにDOMに影響を与えるコードを追加しても画面が点滅することはありません.この機能は、レンダリング前に実行したいアクションまたはレンダリングする状態がEffect内で初期化されている場合に使用できます.
しかし、同期動作で生じる欠点がある.上記のコードがデータをロードする部分であれば、10秒かかると仮定すると、プレイヤーは10秒以内に空白の画面を見ることができます.
useEffectを使用して設計中に点滅の問題が発生した場合は、useLayoutEffectを使用することが望ましい.当初は公式文書でもそう勧められた.(ちゃんと混ぜて使うと良さそう…)

さらに..。



useEffectがpaintより前に発生する場合もあります.
useLayoutEffectでは、ステータスの変更により再表示されます.

useLayoutEffect問題


Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer’s output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client
Next.jsで使用すると、すぐにエラーが発生します.SSRを使用するため、CSRでのみ使用することをお勧めします.しかしSSRでは使いたい場合もあります.(実は、私はこのエラーに遭遇して、Velogを書き始めました...)
//@hooks/useIsomorphicEffect
import { useEffect, useLayoutEffect } from 'react'

export const useIsomorphicEffect = () => {
  return typeof window !== 'undefined' ? useLayoutEffect : useEffect
}
レンダリング後、windowオブジェクトを作成するかどうかによって、useEffectを使用するかuseLayoutEffectを使用するかを決定できます.それをカスタムフックにしましょう.
import React, { useEffect, useLayoutEffect } from 'react'
import { useIsomorphicEffect } from './useIsomorphicEffect'

const App = () => {
  const isomorphicEffect = useIsomorphicEffect()
  
  isomorphicEffect(() => {
    // do something you want
  }, [])
  
  return (
    <div>
      Hellow world
    </div>
  )
}
次に、使用する部分にuseIsomorphicEffectをEffectとして使用します.