🍉

Next.jsでちょっとだけsessionStorageを使わせて

2021/07/25に公開

Next.jsがSSGで静的ページをプリレンダーして高速化してくれるのは大変ありがたいですが、クライアント側のセッション読み書きをほんの少しだけ使いたい時ってありますよね。
useContextはまだしもReduxとか、いやそんな大事にはしたくないんです。
クライアント側で発火するuseEffectでなんとかできないものか。

要件

タグを持っているカードの一覧ページがあって、そこでタグの絞り込みができる。
このページに戻ってきた時に、先ほど指定したタグが適用されていて欲しい。
router.back()などで戻ってきたりすることもあって、クエリパラメータ云々はできない。

Before

const CardListPage = ({ allCards }: Props) => {
  // このページ開くたびにタグが空文字(=未指定)にされる
  const [tag, setTag] = useState('');
  
  // タグ選択やカード一覧は別コンポーネント
  const candidates = ['hoge', 'fuga'];
  return (
    <div>
      <CardTagSelector tag={tag} setTag={setTag} tagCandidates={candidates} />
      <CardList cards={allCards} tag={tag} />
    </div>
  );
}

After

const CardListPage = ({ allCards }: Props) => {
  const [tag, setTag] = useState('');
  // 初回読み込みのスタータス管理
  const [initialLoad, setInitialLoad] = useState(true);
  
  // tag更新時にクライアント側で発火
  useEffect(() => {
    const filterTag = sessionStorage.getItem('filterTag');
    if (initialLoad && filterTag && filterTag !== '') {
      // 初期化タイミングで、前回の指定タグがあったらタグを上書き
      setTag(filterTag);
      // 初期化はもうしない
      setInitialLoad(false);
    } else {
      // 指定したタグを覚えておく
      sessionStorage.setItem('filterTag', tag);
    }
  }, [tag]);
  
  return (
    // 省略
  );
}

どうでしょうか?

setTagが呼ばれた中でsetTag呼ぶのって初回だけにしてるからいいですかね?
これだけのコードでセッションを扱えるようになったので良しとしたいです。

もっと良い方法があったら教えてください。 🙇‍♂️

Discussion