【React】nuqsを使ってstateをURLに保存してみる！

# nuqsとは
公式ドキュメントのスクショです

![cap1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/62f68b6c-db65-21b0-dcc3-96a08059c3df.png)

https://nuqs.47ng.com/

>Type-safe search params state manager for React

とあります。
React用の、型安全なURLクエリパラメータを利用したstate管理ライブラリです。

## URLクエリパラメータを利用したstate管理？
state管理と聞くと、```useState()``` を利用した管理や、```recoil```（古い？）、```redux``` 、```jotai``` を使用した管理などがパッと思いつくと思います。

nuqsでは、このstateをURLのクエリパラメータとして表現し、管理します。
公式ドキュメントのサンプルを触って、どういうことなのか見てみます。

https://nuqs.47ng.com/

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/84093f64-ee4c-a6bc-5ae8-449a9c3ee323.gif)

なんとなく雰囲気が理解できたでしょうか？
inputに入力した値がURL上に現れること、
逆に、URL上のクエリパラメータが画面に反映されることが確認できました。

## URLクエリパラメータを利用したstate管理の個人的推しポイント

**1. ページの共有が簡単（URLに状態が含まれる）！！**
stateがURLに含まれるため、ブックマークやURLを転送しての共有などが簡単に行えます。
filter条件やsort条件などをURL上で管理することで、filter/sort後のページを簡単に表示できます！

**2. ブラウザの戻る/進む/リロードボタンでの状態管理が簡単！！**
上とほぼ同じですが、URLでstateが管理されていれば、このように使えます。
個人的には、リロードしても大丈夫なのがかなり好きです。

なんとなく動作の雰囲気とメリットが把握できたと思うので、実際にはろーわーるどしてみます。

# やってみる
## プロジェクト準備
過去に投稿した記事を参考に、vite + React 環境を用意します。

https://qiita.com/suiwave/items/879ceafdde7d9dd51c1c

毎回めんどくさいのでリポジトリを作りました

https://github.com/suiwave/vite-react-template

## nuqsライブラリの追加
ドキュメントを参考にすすめていきます

https://nuqs.47ng.com/docs/installation

```bash
npm install nuqs
```

## アダプターの追加
vite + React用の項目を参考にアダプターを実装します

https://nuqs.47ng.com/docs/adapters#react-spa

```diff_typescript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
+ import { NuqsAdapter } from 'nuqs/adapters/react'
import './index.css'
import App from './App.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
+   <NuqsAdapter>
      <App />
+   </NuqsAdapter>
  </StrictMode>,
)
```

## 使ってみる
ドキュメントのbasic-usageをまずはやってみます

https://nuqs.47ng.com/docs/basic-usage

ドキュメントを参考に、App.tsxを編集します

```src/app.tsx
import { useQueryState } from 'nuqs'

export function App() {
  const [name, setName] = useQueryState('name')
  return (
    <>
      <input value={name || ''} onChange={e => setName(e.target.value)} />
      <button onClick={() => setName(null)}>Clear</button>
      <p>Hello, {name || 'anonymous visitor'}!</p>
    </>
  )
}

export default App
```

動作を確認してみます！！

```bash
npm run dev
```

![cap2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/a54d60f6-9f1c-388d-95a6-baa26ec7755c.png)

表示はよさそうです

![cap3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ec10dc42-c800-4745-8407-66abdbf93652.png)

URLクエリパラメータでstate管理できてますね！！！

コードを見てわかる通り、nuqsはかなり```useState()``` によせて作られているため、簡単に移行または導入できそうです。

```diff_typescript
-   import { useState } from 'react';
-   const [name, setName] = useState('name')
/* ↓↓↓  */
+   import { useQueryState } from 'nuqs'
+   const [name, setName] = useQueryState('name')
```

ただ、注意が必要なのは、こういったstateをページ遷移先へ持っていきたい場合です。
```react-router-dom``` でもやりようはありますが、微妙な感じもあります。

```tanstack-router``` というライブラリを使用すると、URLでstateを扱いながら型安全にページ遷移まで行えます。

以前記事を書いているので、気になる方はぜひ見てみてください（なんかダイマみたいになったな）

https://qiita.com/suiwave/items/041b98f230bdfa52fa39

# おわりに
今回は[suinさん](https://x.com/suin)のポストに影響され、[nuqs](https://nuqs.47ng.com/)を触ってみました。

https://x.com/suin/status/1849234795546763472

stateの永続化はローカルストレージに保存するのが一般的？な気がしているのですが、
こういった管理も良いなと感じました！！！！