Recoil
最近更新が行われておらず、React 19に対応していないため死亡
悲しいね
Recoilとは
Recoilは、Facebookが開発したReact向けの状態管理ライブラリ。ReduxやMobXなどの他の状態管理ライブラリと比較して、より簡単に実装でき、Reactの機能との親和性が高いのが特徴。
主な特徴
- シンプルなAPI
- Reactのhooks APIとの高い互換性
- 非同期データの扱いやすさ
- 部分的な状態更新による効率的なレンダリング
- TypeScriptのサポート
ユースケース
- グローバルな状態管理が必要な場合
- コンポーネント間で状態を共有する必要がある場合
- 複雑な状態管理が必要な場合
- パフォーマンスの最適化が必要な場合
Recoilの主要概念
1. Atom
- 状態の最小単位
- グローバルに共有される値を保持
- 更新可能で、subscribable(監視可能)
2. Selector
- atomまたは他のselectorから派生した状態
- 状態の加工や計算に使用
- 純粋関数として実装
Recoilのインストール
npm install recoil
Recoil の設定
Recoilを使うためには一番トップのコンポーネントにRecoilRoot
というコンポーネントでラップする必要がある。
layout.tsx
に'use client'
をつけて、クライアントコンポーネントにするとApp Router
のメリットが得られなくなるため、Composition
を利用する。
src/app/recoilProvider.tsx
'use client'
import { ReactNode } from 'react';
import { RecoilRoot } from 'recoil';
function RecoilProvider({ children }: { children: ReactNode }) {
return (
<RecoilRoot>{children}</RecoilRoot>
);
}
export default RecoilProvider;
src/app/layout.tsx
'use client';
//import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import RecoilProvider from './recoilProvider'; //別ファイルで作成したRecoilProviderをインポート
import './globals.css';
const inter = Inter({ subsets: ['latin'] });
// export const metadata: Metadata = {
// title: 'Create Next App',
// description: 'Generated by create next app',
// };
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang='en'>
<body className={inter.className}>
<RecoilProvider>{children}</RecoilProvider>
</body>
</html>
);
}
atomの作成
Recoilの状態管理の核である、atom
(グローバルstate)を作成
- Recoilでは、stateをatomという単位で構成する
- 以下では例として、ユーザーの情報を管理するatomを作成
- keyの値はユニーク
- atom として設定した値は全コンポーネント間で状態が共有される
- atomの値が更新されると、その値を使用しているコンポーネント全てに再レンダリングが走る
以下例
src/atoms/userState.ts
import { atom } from 'recoil'
export type User = {
id: number;
name: string;
email: string;
};
export const userState = atom<User[]>({
key: 'userState',
default: {
id: null,
name: '',
email: ''
}
})
Recoilの主要フック
1. useRecoilState
atomの値の取得と更新の両方が可能です。
const [value, setValue] = useRecoilState(myAtom);
2. useRecoilValue
atomの値の取得のみ可能です。
const value = useRecoilValue(myAtom);
3. useSetRecoilState
atomの値の更新のみ可能です。
const setValue = useSetRecoilState(myAtom);
4. useResetRecoilState
atomの値をデフォルト値にリセットします。
const resetValue = useResetRecoilState(myAtom);
Selectorの使用例
import { selector } from 'recoil';
export const userNameSelector = selector({
key: 'userNameSelector',
get: ({get}) => {
const user = get(userState);
return user.name.toUpperCase();
},
});
ベストプラクティス
- アトムの分割
- 適切な粒度でatomを分割する
- 関連する状態をまとめる
- 型定義の活用
- TypeScriptを使用して型安全性を確保
- 命名規則
- atomは
〜State
- selectorは
〜Selector
- atomは
- パフォーマンス最適化
- 必要な部分のみを更新
- 適切なメモ化の使用
注意点
- Server Side Rendering (SSR)
- RecoilRootはクライアントサイドでのみ動作
- Next.jsでは適切な設定が必要
- 状態の永続化
- デフォルトでは永続化されない
- 必要に応じて別途実装が必要