👷

Global StateにNano Storesという選択肢

2022/10/21に公開

Astroのドキュメントを読んでいたらnanostoresというステート管理ライブラリの存在を知ったので紹介します。

https://astro.build/

https://github.com/nanostores/nanostores

いろいろ書いてありますが、ざっくり以下に注目しました。

  • いろんなフレームワークで使える
  • とにかくバンドルサイズが小さくて高速

実際に触ってみるととてもシンプルで使いやすいと思ったので紹介します。
実際のプロダクトで使用したことはまだないので、使ってみた感想などあれば教えていただきたいです。

サンプル

Reactを使用したサンプルを作ってみました。

動作

stateが保持されたままページ遷移できていることを確認できます。

サンプルコード

storeはnanostoresのimportを覗いてたった1行のコードです。
各ページのコンポーネントからuseStoreで同一のstoreを参照することで、ページを跨いでも保持されたstateを参照できます。

store/count

import { atom } from 'nanostores'

export const count = atom<number>(0)

page1

import { useStore } from '@nanostores/react'
import { count } from '@/stores/count'

const Page = () => {
  const $count = useStore(count)

  return (
    <div>
      <p>ページ1</p>
      <p>{`count: ${$count}`}</p>
      <Button onClick={() => count.set($count + 1)}>increase</Button>
      <Button onClick={() => count.set($count - 1)}>decrease</Button>
      <Button onClick={() => count.set(0)}>clear</Button>
      <Link href={'/page2'}>{'to page2'}</Link>
    </div>
  )
}

page2

import { useStore } from '@nanostores/react'
import { count } from '@/stores/count'

const Page = () => {
  const $count = useStore(count)

  return (
    <div>
      <p>ページ2</p>
      <p>{`count: ${$count}`}</p>
      <Button onClick={() => count.set($count + 1)}>increase</Button>
      <Button onClick={() => count.set($count - 1)}>decrease</Button>
      <Button onClick={() => count.set(0)}>clear</Button>
      <Link href={'/page1'}>{'to page1'}</Link>
    </div>
  )
}

あとがき

これくらいシンプルでよくない?

補足

普段Global Stateをどう扱っているか

  • そもそもグローバルstateをあまり使わないが、必要な場合はRecoilかuseContextを使うことが多い。
  • Recoilを使用する場合、_app.tsxにRecoilRootを配置してほぼグローバルステートのようにしか使っていない。
  • APIのレスポンスはReactQueryなどを使用している (しかしあまりキャッシュを使用することはない)。

Discussion