😺

Webサイトの状態管理にnanostoresを使ってみて

に公開

「Web制作」でも状態管理が必要か?

従来のWeb制作では、静的HTMLやアニメーションをjQueryなどで実装することが多く「状態管理」という概念が必要になる場面はほとんどありませんでした。
しかし近年では、AstroやReactを用いたSPA(Single Page Application)やSSG(Static Site Generation)の構成でWebサイトを構築するケースも増えています。
そのような構成では、CMSとAPI連携を行い、複数のUIコンポーネント間で状態(たとえばフィルター選択やテーマ切り替えなど)を共有する必要が出てきます。

ただし、Webアプリケーションのように複雑なロジックを持たないWebサイトでは、Reduxのような重量級ライブラリを導入するのはオーバースペックであり、学習コストも見合いません。
そういった「中間層」のニーズにフィットするのが、nanostoresです。

nanostoresとは

nanostoresは、軽量でフレームワーク非依存の状態管理ライブラリです。
サイズが圧縮・ブロット化後でわずか265〜797バイトで依存関係も無いとの事。
また、Typescriptにも対応しているようでした。
https://github.com/nanostores/nanostores?utm_source=chatgpt.com

使い方

基本パッケージに加え、Reactなどで利用する際は、フレームワーク統合パッケージも導入します。
まずはインストール

npm install nanostores
npm install @nanostores/react

主要な機能

Atoms

プリミティブな値を保持できます。

import { atom } from 'nanostores'

export const $counter = atom(0)

Reactとの統合(@nanostores/react)

Reactでは、useStore() フックを使用してストアを購読できます。
これにより、ストアが更新されるとコンポーネントも自動で再レンダリングされます。

// components/Counter.tsx
import React from 'react'
import { useStore } from '@nanostores/react'
import { $counter } from '../stores/counter'

export function Counter() {
  const count = useStore($counter)

  return (
    <div>
      <p>現在のカウント: {count}</p>
      <button onClick={() => $counter.set(count + 1)}>+1</button>
    </div>
  )
}

Maps

オブジェクト構造の状態を扱う場合は map() を使用します。

// stores/profile.ts
import { map } from 'nanostores'

export interface Profile {
  name: string
  email?: string
}

export const $profile = map<Profile>({
  name: 'anonymous'
})

Persistentストア

@nanostores/persistent を使うと、localStorageに自動保存され、
ページリロードやタブ間でも同期できます。

  • インストール
npm install @nanostores/persistent
  • 使い方
import { persistentAtom } from '@nanostores/persistent'

export const $theme = persistentAtom<'light' | 'dark'>('theme', 'light')

実用的なメリット

  • ページリロードしてもデータが残る(Persistent使用時)
  • 複数タブで状態が同期される
  • 無駄な再レンダリングを防げる
  • ReduxのようなProvider設定や中間層が不要
  • フレームワーク間で状態を共有できる

まとめ

Webアプリケーションほど複雑ではないが、コンポーネント間で状態共有が必要な中規模サイトでは、nanostores が軽量かつ実用的な選択肢です。Reduxのような複雑な構成は不要で「使いたい箇所で使える状態管理」が実現できます。

参考

https://zenn.dev/052hide/articles/global-state-nanostores
https://github.com/nanostores/nanostores?utm_source=chatgpt.com

Discussion