最近Recoilの学習をし、useContextより簡単だと感じたため、備忘録も兼ねてまとめます。
ステートの定義
ステートを定義する際は、recoil
が提供するatom
という関数を利用する。
userState.js
import { atom } from "recoil";
export const userState = atom({
key: "userState",
default: { bool: true, name: "Hello" }
});
key: ステートを認識するための一意の値を設定
default: ステートの初期値
グローバルステートの定義はこれだけでOK。
useContextよりはるかに楽!!
状態管理の設定
Recoilで状態管理をできるようにするために、親コンポーネントをRecoilRoot
というコンポーネントで囲う。
今回はApp.js全体で参照できるように、App.jsを囲む形で設定。
App.js
import { createRoot } from "react-dom/client";
import { RecoilRoot } from "recoil";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<RecoilRoot>
<App />
</RecoilRoot>
);
ステートの参照・受け渡し
定義したステートを参照するには、useRecoilState
という関数を利用。
※今回はApp.js内ではこれらの値は使用しない。
import "./styles.css";
import { useRecoilState } from "recoil";
import { userState } from "./store/userState";
export default function App() {
// stateとセット関数の命名はこの時に行えば良い。
const [state, setState] = useRecoilState(userState);
}
続いて、参照用のコンポーネントと更新用のコンポーネントを作成。
参照用(Sample1.jsx)
import { useRecoilValue } from "recoil";
import { userState } from "./store/userState";
export const Sample1 = () => {
const state = useRecoilValue(userState);
console.log("Sample1 - 更新" + state.bool);
return <p>{state.name}</p>;
};
この時、参照用ではステートの値だけ持って来れば良い。そこで利用するのは、useRecoilValue
という関数。
更新用(Sample2.jsx)
import { useSetRecoilState } from "recoil";
import { userState } from "./store/userState";
export const Sample2 = () => {
const setState = useSetRecoilState(userState);
const updateTrue = () => {
setState({ bool: true, name: "Hello" });
};
const updateFalse = () => {
setState({ bool: false, name: "Hello" });
};
console.log("Sample2 - 更新");
return (
<>
<button onClick={updateTrue}>Trueに変更</button>
<button onClick={updateFalse}>Falseに変更</button>
</>
);
};
この時、更新用ではステートを更新するセット関数だけを持って来れば良い。そこで利用するのは、useSetRecoilState
という関数。
これらをApp.jsにインポートして確認してみる。
結果は以下の通り。
ここで試しにボタンをクリックし、ステートの値を更新してみる。
すると見て分かる通り、コンポーネントの更新がSample1
しかされていないことが分かる。
これはRecoilの仕様であり、更新関数のみを取得しているコンポーネントは、ステートが更新されても再レンダリングされないようになっている。
※注意点
Sample2.jsxの親コンポーネント(今回でいうApp.js)が更新されれば、当然Sample2.jsxも更新されてしまう。
この場合はReact hooksのmemo
を利用して対策する必要がある。