0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Event listenerでのRecoil Value更新

Last updated at Posted at 2022-08-29

自己学習メモ

Recoilは状態管理として簡単に使えるが、たまにつまりポイントがあるのでそのあたりのメモ
※Recoilがどこでもよしなに更新してくれるだろうくらいで思っているとつまる

環境

  • react": "^18.2.0"
  • recoil": "^0.7.5"

コンポーネント描画時にイベント登録を行いRecoilが後で更新されたケース
以下では、resizeイベントを登録してボタンでRecoilを更新する

Valueが更新されないコード

useEffectで一度だけイベント登録して、listenerで参照する場合
atomが更新されてもlistenerのなかでは古い情報が参照される

import { useEffect } from "react";
import { atom, useRecoilState } from "recoil";

const isLoginAtom = atom({
  key: "isLogin",
  default: false,
});

const Test: React.FC = () => {
  const [isLogin, setIsLogin] = useRecoilState(isLoginAtom);
  const resizeEvent = (_e: Event) => {
    console.log("isLogin", isLogin);
  };

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

  return <button onClick={() => setIsLogin(!isLogin)}>LOGIN</button>;
};

export default Test;

Recoil Valueが更新されるコード

useEffectのdependencyにlistenerを指定
listenerの中で最新のValueが取得される

import { useEffect } from "react";
import { atom, useRecoilState } from "recoil";

const isLoginAtom = atom({
  key: "isLogin",
  default: false,
});

const Test: React.FC = () => {
  const [isLogin, setIsLogin] = useRecoilState(isLoginAtom);
  const resizeEvent = (_e: Event) => {
    console.log("isLogin", isLogin);
  };

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

  return <button onClick={() => setIsLogin(!isLogin)}>LOGIN</button>;
};

export default Test;

Recoil Valueが更新されるコード2

Recoilのsnapshotから最新Valueを取得

import { useEffect } from "react";
import {
  atom,
  RecoilState,
  RecoilValue,
  useRecoilCallback,
  useRecoilState,
} from "recoil";

const isLoginAtom = atom({
  key: "isLogin",
  default: false,
});

const Test: React.FC = () => {
  const [isLogin, setIsLogin] = useRecoilState(isLoginAtom);
  const getRecoilStateSync = useRecoilCallback(
    ({ snapshot }) =>
      (state: RecoilState<unknown> | RecoilValue<unknown>): unknown => {
        return snapshot.getLoadable(state).contents;
      },
    []
  );

  const resizeEvent = (_e: Event) => {
    const isLogin = getRecoilStateSync(isLoginAtom);
    console.log("isLogin", isLogin);
  };

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

  return <button onClick={() => setIsLogin(!isLogin)}>LOGIN</button>;
};

export default Test;

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?