matsutoba’s blog

フロントエンドエンジニアをしています

Reactでのstateの変更とイベントの再登録について

windowにクリックイベントを登録して、クリックしたときにstateの状態によって処理を切り分けたいので、こう書いてみた。

import { useState, useEffect, useMemo } from "react";

export default function App() {
  const [id, setId] = useState("");

  const handler = () => {
    console.log("id", id);
    if (id === "1") {
      console.log("OK");
    } else {
      console.log("NG");
    }
  };

  useEffect(() => {
    window.addEventListener("click", handler);
    return () => {
      window.removeEventListener("click", handler);
    };
  }, []);

  console.log("State id", id);

  return (
    <div>
      <button
        onClick={() => {
          setId("0");
        }}
      >
        Set 0
      </button>
      <button
        onClick={() => {
          setId("1");
        }}
      >
        Set 1
      </button>
    </div>
  );
}

ボタンを押すとstateの状態が変わって再レンダリングされるのに、リスナに設定した関数の中は以前のstateの値を持ったままになってしまう。

イベントの登録をするuseEffectに依存配列としてstateの値を設定して、stateが変わったときにイベントを登録しなおせば、期待通りの動作になった。

  useEffect(() => {
    window.addEventListener("click", handler);
    return () => {
      window.removeEventListener("click", handler);
    };
  }, [id]);