Hooks - useEffect


Side Effect

Side Effect:副作用、副作用.
名前を聞くだけではネガティブな意味があるようです.
ただし、関数構成部品では、Side Effectは、関数の実行時に関数の外部状態を変更する演算にすぎません.
レンダリング以外の関数の外部環境に影響を与えるイベントといえます._ex) API 호출, Data Fetching, 이벤트 처리함수 등록 및 해제_関数要素の戻り値はUI要素で、状態値とpropsが変化すると関数が実行されます.
つまり、エレメントをレンダーするたびに関数ボディの論理が実行され、レンダーに関係のない論理が各レンダー中に実行され、レンダー自体のパフォーマンスに悪影響を及ぼす可能性があります.useEffectは、レンダリングに関係のないSide Effectのリアクターをユーザが実行できるようにする内蔵フックである.

RenderingCycleとUserEffect


useEffectをより広く使用するには、反応素子のRendering Cycleを理解する必要がある.
反応素子のレンダリングサイクルに応じて、userEffectのライフサイクルを下図に示します.
  • 構成部品をレンダリングします.最初のレンダリングは、ブラウザで初めて描画されます(mount).
  • userEffectの最初のパラメータによって伝達される負の効果関数が実行される.
  • 再レンダリング(re-render)が発生した場合(stateまたはpropsを変更した場合)、userEffectは2番目のパラメータの依存配列を確認します.前述したように、パラメータをuserEffectに渡す配列に従って浮動小数点効果関数を実行または実行しない.
  • 前述のEffectでstateまたはpropsが変更された場合は、再レンダリングされます.
  • 以降は、素子を必要としないと画面から消えてしまう(unmount).
  • useEffectの使用


    useEffect hook内の関数を賦値効果関数と呼ぶ.
    浮動小数点エフェクト関数はレンダリング後に呼び出され、コンポーネントが消える前に最後に呼び出されます.
    const Example = () => {
      const [count, setCount] = useState(0);
      
      useEffect(() => {
      	document.title = `update count : ${count}`;
      });
      
      return (
      	<div>
          <button onClick={() => setCount(prev => prev+1)}>push</button>
        </div>
      );
    }
    たとえば、上記の例では、ボタンをクリックするたびに再レンダリングが行われ、レンダリング後にuserEffectが実行されます.
    ただし、このように状態値を変更すると、各レンダリングでuserEffectを呼び出すとパフォーマンスが低下します.
    const Example = () => {
      const [count1, setCount1] = useState(0);
      const [count2, setCount2] = useState(0);
      
      useEffect(() => {
      	document.title = `update count : ${count1}`;	
      }, [count1]); // count1의 값이 변경되었을 때만 useEffect가 실행된다.
      
      return (
      	<div>
          <button onClick={() => setCount1(prev => prev+1)}>count1 push</button>
          <button onClick={() => setCount2(prev => prev+1)}>count2 push</button>
        </div>
      );
    }
    userEffectは、付随する効果関数に加えて、依存配列(dependancy array)をパラメータとして受け入れることができ、この場合、配列内の値が変化した場合にのみuserEffectを実行させることができる.
    また、空の配列[]をuserEffectの2番目のパラメータとして使用すると、素子の1回目のレンダリング後に1回実行でき、他の値の変更が発生してもその配列は実行されません.
    useEffectは、unmount(前のクラスの要素のcomponentWillUnmountと同じ)で作成され、クリア関数を実行できます.
    const Example = () => {
      const [scrollCount, setScrollCount] = useState(0)
      const onScroll = () => {
        setScrollCount(prev => prev + 1)
      }
      
      useEffect(() => {
      	document.addEventListener("scroll", onScroll)	
        
        return () => window.removeEventListener("scroll", onScroll)
      }, []); // 컴포넌트가 마운트될 때 onScroll을 이벤트리스너에 등록하고, 언마운트될 때 해제한다.
      
      return (
      	<div>
          <p>scroll! : {scrollCount}</p>
        </div>
      );
    }
    上記の例に示すように、cleanup関数をuserEffectのパラメータとしての付与関数に戻すだけでよい.
    これにより、エレメントがアンインストールされると、userEffectは戻ってくるクリーンアップ関数を実行し、エレメントは画面から消えてしまいます.