システム開発で思うところ

Javaで主にシステム開発をしながら思うところをツラツラを綴る。主に自分向けのメモ。EE関連の情報が少なく自分自身がそういう情報があったら良いなぁということで他の人の参考になれば幸い

LocalStorageを扱うHooks

何が嬉しいの?

Windowをまたがった情報共有ができる。
ただし多用すると状態管理が散乱するので避けた方良い。

実装

import { useEffect, useState, useRef } from 'react';

const useCrossWindowState = <T>(
  stateKey: string,
  defaultValue: T,
): [state: T, setState: (state: T) => void] => {
  const [state, setState] = useState<T>(defaultValue);
  const isNewSession = useRef(true);

  useEffect(() => {
    if (isNewSession.current) {
      const currentState = localStorage.getItem(stateKey);
      if (currentState) {
        setState(JSON.parse(currentState));
      } else {
        setState(defaultValue);
      }
      isNewSession.current = false;
      return;
    }
    try {
      localStorage.setItem(stateKey, JSON.stringify(state));
    } catch (error) {}
  }, [state, stateKey, defaultValue]);

  useEffect(() => {
    const onReceieveMessage = (e: StorageEvent) => {
      const { key, newValue } = e;
      if (key === stateKey) {
        setState(JSON.parse(newValue ?? ''));
      }
    };
    window.addEventListener('storage', onReceieveMessage);
    return () => window.removeEventListener('storage', onReceieveMessage);
  }, [stateKey, setState]);

  return [state, setState];
};

export default useCrossWindowState;

使い方
useStateと同じ感じ。

const [volume, setVolume] = useCrossWindowState<number>('audioVolume', 15);

参考

react-cross-windows-state - CodeSandbox

さいごに

TypeScript対応をするときの型を探すのが地味に手間。
でもanyに逃げない*1

*1:今回だとStorageEvent