React学習ちまちま開始。
自分向けの備忘録。

import { useEffect, useState } from "react";

const Example = () => {
  const [time, setTime] = useState(0);

  // useEffect(() => {
  // 1秒ごとにsetTime関数を呼び出し、その度に再レンダリングされてしまい、秒カウントがおかしい挙動となってしまう
  // コンポーネントが呼ばれた時に1回だけ呼びたい場合はuseEffectのコールバック関数内で呼びたい処理を記述する
    window.setInterval(() => {
      setTime((prev) => prev + 1);
    }, 1000);
  // }, []);

  return (
    <h3>
      <time>{time}</time>
      <span>秒経過</span>
    </h3>
  );
};

export default Example;

依存配列

useEffectの第二引数にセットされる配列は依存配列と呼ばれる。この配列に含まれるStateが更新されると、そのuseEffectも更新される。

import { useEffect, useState } from "react";

const Example = () => {
  const [time, setTime] = useState(0);

  // 依存配列が空の場合は、依存するStateがないので、コンポーネントが生成されたときのみ実行される
  // 依存配列をかき忘れてしまうと、useEffectの挙動は実現できないので忘れずに書く
  useEffect(() => {
    window.setInterval(() => {
      setTime((prev) => prev + 1);
    }, 1000);
  }, []);

 // 1秒ごとにtimeが更新されるたびに呼ばれる
  useEffect(() => {
    console.log("TEST");
  }, [time]);

  return (
    <h3>
      <time>{time}</time>
      <span>秒経過</span>
    </h3>
  );
};

export default Example;

※useEffectが依存しているStateをそのuseEffect内で更新してしまうと無限ループとなってしまう。

クリーンアップ関数

useEffectの戻り値には関数を設定することができ、それをクリーンアップ処理と呼ぶ。
そのコンポーネントがアンマウントとなった際に行われる処理を設定することができる。
※クリーンアップ処理を設定しないとコンポーネントが削除された際も裏側でずっと動き続けるととなるため、メモリーリークに繋がる

import { useEffect, useState } from "react";

const Example = () => {
  const [isDisp, setIsDisp] = useState(true);

  return (
    <>
      // isDispがTrueの場合にタイマーを表示
      {isDisp && <Timer />}
      <button onClick={() => setIsDisp((prev) => !prev)}>トグル</button>
    </>
  );
};

const Timer = () => {
  const [time, setTime] = useState(0);

  useEffect(() => {
    let intervalId = null;
    intervalId = window.setInterval(() => {
      setTime((prev) => prev + 1);
    }, 1000);

    return () => {
      // コンポーネントが削除された際の処理。
    // 今回は秒カウントコンポーネントがアンマウントされた際にカウントをストップする。
    // この処理がないとコンポーネントが削除された際にも裏で永遠にカウントされてしまう 
      window.clearInterval(intervalId);
    };
  }, []);

  return (
    <h3>
      <time>{time}</time>
      <span>秒経過</span>
    </h3>
  );
};

export default Example;

※もし依存配列が設定されている場合、
依存配列が更新される→クリーンアップ関数が呼ばれる→コールバック関数が呼ばれる
という順番。

useEffectとuseLayoutEffectの違い

・useEffectはページが描画した後、非同期的に行われる
・useLayoutEffectはページが描画される前に同期的に実行

なのでuseLayoutEffectはuseEffectよりも先に実行される

【参考】
・Udemy:【2024年最新】React(v18)完全入門ガイド
・React実践入門

c.sakyou

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA