こんにちは、フリーランスエンジニアの太田雅昭です。
Jotai
Jotaiは日本の方が作られたReactの状態管理ライブラリです。
とてもシンプルなのに関わらず、いまだに全てを使いこなせていませんが、その便利な機能のひとつを今回ご紹介させていただきます。
通常の使い方
通常は以下のようにして使うかと思います。シンプルなCount Upです。
import { atom, useAtomValue, useSetAtom } from "jotai";
const countAtom = atom<number>(0);
export default function App() {
// 一度だけ呼ばれる
console.log("render App");
return (
<div>
<Count />
<CountUpButton />
</div>
);
}
function Count() {
// Count Upごとに呼ばれる
console.log("render Count");
const count = useAtomValue(countAtom);
return count;
}
function CountUpButton() {
// 一度だけ呼ばれる
console.log("render CountUpButton");
const setCount = useSetAtom(countAtom);
return <button onClick={() => setCount(c => c + 1)}>Count Up</button>;
}
副作用を伴う使用
続けて、このcountをログするだけのロジックを書いてみます。
Jotaiを活かさない書き方
通常のフックを使うとJotaiの良さが生きてきません。以下の例では、フックを読み込むコンポーネントで不要な再レンダリングが発生しています。
import { atom, useAtomValue, useSetAtom } from "jotai";
const countAtom = atom<number>(0);
// countをログするフック
function useLogCount() {
// ここでcountを参照している
const count = useAtomValue(countAtom);
const logCount = () => console.log(count);
return { logCount };
}
export default function App() {
const setCount = useSetAtom(countAtom);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count Up</button>
<LogCountButton />
</div>
);
}
function LogCountButton() {
const { logCount } = useLogCount();
// count更新時に、本来不要な再レンダリングが起きる
console.log("render LogCountButton");
return (
<button onClick={() => logCount()}>
Log Count
</button>
);
}
Jotaiを活かした書き方
以下のようにjotaiでロジックを書くと、不要な再レンダリングを防ぐことができます。
import { atom, useAtomValue, useSetAtom } from "jotai";
const countAtom = atom<number>(0);
// atomでログ関数を作成する
const logCountAtom = atom(null, (get, set) => {
const count = get(countAtom);
console.log(count);
});
export default function App() {
const setCount = useSetAtom(countAtom);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count Up</button>
<LogCountButton />
</div>
);
}
function LogCountButton() {
const logCount = useSetAtom(logCountAtom);
// count変更による再レンダリングが起きない
console.log("render LogCountButton");
return (
<button onClick={() => logCount()}>
Log Count
</button>
);
}
まとめ
Jotaiはグローバルステートを持てる以外にも、パフォーマンス最適化にも優れていることが分かりました。すごいですね。