ReactuseEffectフック


フックを使用すると、useEffectコンポーネントで副作用を実行できます。

副作用の例としては、データのフェッチ、DOMの直接更新、タイマーなどがあります。

useEffect2つの引数を受け入れます。2番目の引数はオプションです。

useEffect(<function>, <dependency>)


例としてタイマーを使用してみましょう。

例:

setTimeout()最初のレンダリングから1秒後にカウントするために使用します。

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  });

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById('root'));

ちょっと待って!!一度だけ数えるべきなのに数え続けます!

useEffectすべてのレンダリングで実行されます。つまり、カウントが変更されると、レンダリングが発生し、それが別の効果をトリガーします。

これは私たちが望んでいることではありません。副作用がいつ実行されるかを制御する方法はいくつかあります。

配列を受け入れる2番目のパラメーターを常に含める必要があります。useEffectオプションで、この配列に依存関係を渡すことができます。

1.依存関係は渡されません:

useEffect(() => {
  //Runs on every render
});

2.空の配列:

useEffect(() => {
  //Runs only on the first render
}, []);

3.小道具または状態値:

useEffect(() => {
  //Runs on the first render
  //And any time any dependency value changes
}, [prop, state]);

したがって、この問題を修正するには、最初のレンダリングでのみこのエフェクトを実行してみましょう。

例:

最初のレンダリングでのみエフェクトを実行します。

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  }, []); // <- add empty brackets here

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById('root'));

例:

useEffectこれは、変数に依存するフックの例です。count変数が更新されると、エフェクトが再度実行されます

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Counter() {
  const [count, setCount] = useState(0);
  const [calculation, setCalculation] = useState(0);

  useEffect(() => {
    setCalculation(() => count * 2);
  }, [count]); // <- add the count variable here

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount((c) => c + 1)}>+</button>
      <p>Calculation: {calculation}</p>
    </>
  );
}

ReactDOM.render(<Counter />, document.getElementById('root'));

useEffect複数の依存関係がある場合は、それらを依存関係配列に含める必要があります。


w3schools CERTIFIED . 2022

認定を受けましょう!

Reactモジュールを完了し、演習を行い、試験を受けて、w3schools認定を取得してください!!

95ドル登録

エフェクトのクリーンアップ

一部のエフェクトでは、メモリリークを減らすためにクリーンアップが必要です。

タイムアウト、サブスクリプション、イベントリスナー、および不要になったその他の効果は破棄する必要があります。

useEffectこれを行うには、フックの最後にreturn関数を含めます。

例:

useEffectフックの最後でタイマーをクリーンアップします。

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    let timer = setTimeout(() => {
    setCount((count) => count + 1);
  }, 1000);

  return () => clearTimeout(timer)
  }, []);

  return <h1>I've rendered {count} times!</h1>;
}

ReactDOM.render(<Timer />, document.getElementById("root"));

注:タイマーをクリアするには、名前を付ける必要がありました。


エクササイズで自分をテストする

エクササイズ:

フックの2番目の引数に何を追加してuseEffect、最初のレンダリングでのみ実行されるように制限する必要がありますか?

import { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    setData(getData())
  }, );

  return <DisplayData data={data} />;
}

ReactDOM.render(<App />, document.getElementById('root'));