フロントエンドは、よくVueを使っているプロジェクトにいることが多いのですが、ここ最近は個人の時間でReactを勉強していました。状態管理ライブラリを探していたところRecoilというものがあることを知り、少し触れてみました。
この記事ではAtomの使い方について、簡単に書いておこうかと思います。
https://recoiljs.org/docs/introduction/core-concepts#atoms
環境
viteを使いプロジェクトを作成します。React + TypeScript のテンプレートを指定しています。
npm create vite@latest recoil-my-playground -- --template react-ts
ディレクトリに移動して、Recoilをインストールします。
npm install recoil
package.json の中身は次のとおりです。これを書いている時点でのRecoilのバージョンは、0.7.7 でした。
{ "name": "recoil-my-playground", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview" }, "dependencies": { "react": "^18.3.1", "react-dom": "^18.3.1", "recoil": "^0.7.7" }, "devDependencies": { "@eslint/js": "^9.8.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", "eslint": "^9.8.0", "eslint-plugin-react-hooks": "^5.1.0-rc.0", "eslint-plugin-react-refresh": "^0.4.9", "globals": "^15.9.0", "typescript": "^5.5.3", "typescript-eslint": "^8.0.0", "vite": "^5.4.0" } }
atom を定義する
atomは状態の最小限単位です(名前からも最小単位であることが想像しやすいですね)。Recoilではatomを定義し、Reactコンポーネントがatomの値を読み込み/書き込みすることができるようになっています。
atomは次のように定義できます。
import { atom } from "recoil"; export const helloTypographyState = atom<string>({ key: "helloTypographyState", default: "this is read from recoil atom", });
ここでは、helloTypographyState を定義しました。このatomはstring型の値を保持し、デフォルトが this is read from recoil atomとしています。Reactコンポーネントはこの値にアクセスすることができます。
atom を読み込む
atomを読み込むにはuseRecoilValueを使います。useStateと同じ感じです。
上記のatomを読み込んで画面に表示するコンポーネントは次のように実装できます。
import { useRecoilValue } from "recoil"; import { helloTypographyState } from "../store/HelloTypographyState"; export function HelloTypography() { const helloTypography = useRecoilValue(helloTypographyState); return <h1>Hello, {helloTypography}</h1>; }
atomを使うことでコンポーネントが表示する文字列を、コンポーネントから切り離して管理することができました。
atom を書き込む
atomを書き込むにはuseSetRecoilStateを使います。
次のButtonChangeHelloTypographyコンポーネントでは、先ほど定義した helloTypographyStateをChangeに変更します。
import { useSetRecoilState } from "recoil"; import { helloTypographyState } from "../store/HelloTypographyState"; export function ButtonChangeHelloTypography() { const setHelloTypography = useSetRecoilState(helloTypographyState); return <button onClick={() => setHelloTypography("Change")}>Change</button>; }
これで、同じatomを共有する2つのReactコンポーネントを定義することができました。atomの値は変化が起きると値を読み込んでいるコンポーネントは最新の値で再レンダリングされる仕組みになっています。そのため、atomを書き込むコンポーネントはatomの値をどのように変更すればよいかだけに注力すればよく、再レンダリングをしなければならないReactコンポーネントや、再レンダリングのタイミングはRecoilが管理してくれます。