React RecoilでグローバルなStateを作成する
React
+TypeScript
の環境で、Recoil
を使用して、グローバルな状態State
(グローバル変数)を作成します。
React createContextでグローバルなStateを作成するでcreateContext
を使用したグローバル変数を作成しましたが、Recoil
を使えばもっとシンプルにグローバル変数作成できます。
パッケージのインストール
まずはRecoil
のパッケージをインストールします。
$ npm install recoil
ルートコンポーネントの修正
以下のように、ルートコンポーネントにRecoilRoot
を追加します。
RecoilRoot
の子コンポーネントの全てで、Recoil
のグローバル変数が使用できるようになります。
import { RecoilRoot } from 'recoil';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
</React.StrictMode>
);
atomの作成
Recoil
ではグローバル変数はatom
を使用して作成します。
import { atom } from 'recoil';
const loadingState = atom<boolean>({
key: 'loadingState', // プロジェクト全体でユニークとなる値
default: false,
});
atom<型>
の形式でグローバル変数を定義します。
key
にはプロジェクト全体でユニークとなる値を設定します。
規模が大きいプロジェクトの場合はkey
の値は別ファイルで管理したほうが良いかと思います。
default
には初期値を設定します。
カスタムフックの作成
作成したatom
はuseRecoilState(atom変数)
で参照します。
各コンポーネントでuseRecoilState
で参照する形でも問題ありませんが、ここではカスタムフックを作成します。
グローバル変数のゲッター、セッターだけではなく、グローバル変数を使用した共通処理もグローバルファンクションとして一緒に定義することが多いと思うので、カスタムフックとして定義しておき、各コンポーネントでカスタムフックを経由して使用します。
useApp.tsx
import { useCallback } from 'react';
import { atom, useRecoilState } from 'recoil';
const loadingState = atom<boolean>({
key: 'loadingState', // プロジェクト全体でユニークとなる値
default: false,
});
export const useLoading = () => {
const [loading, setLoading] = useRecoilState(loadingState);
return {
loading,
setLoading,
toggleLoading: useCallback(() => {
setLoading((current) => !current);
}, [setLoading]), // 必要に応じて独自のファンクションも追加
};
};
useRecoilState
はuseState
と同じように[ゲッター, セッター]
の形で使用できます。
使い方
以下のように使用します。
カスタムフックを経由して参照すれば、React createContextでグローバルなStateを作成するで紹介したcontext
を使用する場合と同じ方法で参照することができます。
MyComponent.tsx
import useApp from './useApp';
const MyComponent = () => {
// recoilの値を参照可能
const { loading, setLoading } = useApp();
};