recoilとlocalStorageを使って状態の永続化をしたはいいけど、 localStorageのremoveItemをしたい時にどうすればいいか、 試してて多分これが正解かなーっと思いましたので共有します。 間違ってたらコメントくださいm(_ _)m

localStorageEffect

サンプル見るとnewValueが instanceofで DefaultValue ならremoveItem と書いてあります。 ここを通るようにすれば removeItem できました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { AtomEffect, DefaultValue } from "recoil";

export const localStorageEffect: <T>(key: string) => AtomEffect<T> =
  (key: string) =>
  ({ setSelf, onSet }) => {
    if (typeof window !== "undefined") {
      const savedValue = localStorage.getItem(key);
      if (savedValue != null) {
        setSelf(JSON.parse(savedValue));
      }

      onSet((newValue) => {
        if (newValue instanceof DefaultValue) {
          localStorage.removeItem(key);
        } else {
          localStorage.setItem(key, JSON.stringify(newValue));
        }
      });
    }
};

Atom

Atomには、stringDefaultValue が入るように型を指定

1
2
3
4
5
6
7
8
9
import { atom, DefaultValue } from "recoil";

import { localStorageEffect } from "./localStorageEffect";

export const localStorageState = atom<string | DefaultValue>({
  key: 'key',
  default: "",
  effects_UNSTABLE: [localStorageEffect('localstorage_key')],
});

独自フック

1
2
3
4
5
6
7
8
9
10
11
12
13
import { DefaultValue, useRecoilState } from "recoil";

import { localStorageState } from "./localStorageState";

export const useLocalStorage = () => {
  const [value, setValue] = useRecoilState(localStorageState);

  const removeValue = () => {
    setValue(new DefaultValue());
  };

  return { value, setValue, removeValue };
};