目次
Recoilとは何か?
RecoilはオープンソースのReact状態管理ライブラリで、Facebookによって2020年5月14日に作られました。まだ実験段階のライブラリですが、すでに16.6kのスターをgithubで獲得していて、すでに人気になりつつあります。
Recoilの良さは?
簡単に言うと、Reduxに必要な「action, reducer」、React.contextに必要な「provider」なしで状態管理ができます。なので、Reduxより少ないコード量で書け、React.contextよりコードが汚くなりづらいです。
また、ReduxとRecoilは思想も少し異なります。
Reduxは1つの巨大なグローバルストアを作り、そこから役割ごとのストアに分割していくイメージです。
一方でRecoilは"Atoms"と名付けられた複数のストアを持ち、それぞれを独立したものとして使うことができます。
Recoilで1つのグローバルストアを使って状態管理することもできるので、プロジェクトの内容によって柔軟に変更しつつ使用することができます。
Recoilの弱点は?
Facebookが作成したライブラリではあるものの、あくまで実験段階なので開発がストップする可能性もあります。開発されて間もないライブラリなので、まだまだ情報が少ないのもネックになるかもしれません。
ここからは簡単にRecoilの使い方を紹介します。
例:簡単なカウンターアプリ
1. ライブラリをインストールします。npm install recoil
2. プロジェクトを作成します。私はcreate react appのコマンドを用いてプロジェクトを作成しましたが、やり方はお好みで。
npx create-react-app my-counter-app // プロジェクト名はお好みで、移動も忘れずにRecoilRootをrecoilからインポートし、ラップしたいコンポーネントをReactRootで挟みます。(React.contextのプロバイダーと同じ使い方ですね)。
//App.js
import "./App.css";
import { RecoilRoot } from "recoil";
import Counter from "./Counter";
const App = () => {
return (
<div className="App">
<RecoilRoot>
<Counter />
</RecoilRoot>
</div>
);
};
export default App
カウンターコンポーネントを作成し、そちらにrecoilの"atom","useRecoilStateをインポートします。atomを使ってstoreを作り、useRecoilStateでそのstoreを使用するイメージです。//Counter.js
import React from "react";
import { atom, useRecoilState } from "recoil";
export const counterState = atom({
key: "counterState",
default: 0,
});
const Counter = () => {
const [count, setCount] = useRecoilState(counterState);
const handleIncrement = () => {
setCount(count + 1);
};
const handleDecrement = () => {
setCount(count - 1);
};
return (
<>
<p>{count}</p>
<button onClick={handleIncrement}>increment</button>
<button onClick={handleDecrement}>decrement</button>
</>
);
};
export default Counter
以下が出来上がったアプリです。ちゃんと動いているのがわかると思います。
ここまで簡単なアプリだと良さが伝わりづらいですが、ポイントは作成したcounterStateがエクスポート可能で他のファイルでも簡単に状態が共有できる点です。
例えば、以下のようなファイルを作成して先程作成したcounterStateをインポートすると、カウンターの数値がシンクロします。同じstoreの情報を表示しているからですね。
ここまで簡単なアプリだと良さが伝わりづらいですが、ポイントは作成したcounterStateがエクスポート可能で他のファイルでも簡単に状態が共有できる点です。
例えば、以下のようなファイルを作成して先程作成したcounterStateをインポートすると、カウンターの数値がシンクロします。同じstoreの情報を表示しているからですね。
//SecondCounter.js
import React from "react";
import { counterState } from "./Counter";
const SecondCounter = () => {
const [count, setCount] = useRecoilState(counterState);
const handleIncrement = () => {
setCount(count + 1);
};
const handleDecrement = () => {
setCount(count - 1);
};
return (
<>
<p>{count}</p>
<button onClick={handleIncrement}>increment</button>
<button onClick={handleDecrement}>decrement</button>
</>
);
};
export default SecondCounter
以下のような挙動になります。なぜシンクロすると良いのか、というところですが、コンポーネントを分けた時に状態の共有が簡単になるからです。propsを使って状態を渡す必要がなくなるので、よりコードを追うのが簡単になります。
さらに、必要に応じて"読み込み専用"、"書き込み専用"のstateも準備されています。
使うかどうかは好みですが、使い分けることでより可読性の向上につながるでしょう。
使うかどうかは好みですが、使い分けることでより可読性の向上につながるでしょう。
//読み込み専用
const [count] = useRecoilState(counterValue);
const count = useRecoilValue(counterValue);
//書き込み専用
const [, setCount] = useRecoilState(counterValue);
const setCount = useSetRecoilState(counterValue);
まとめ
最初にお伝えした通り、Recoilはまだexperimental(実験段階)のライブラリです。ただ、非常に使いやすいライブラリなので、今後覇権を握る可能性もあると考えています。
VuexやPiniaのgetterと似た使い方ができるselectorを始め、まだまだたくさんの機能がRecoilにはあります。興味がありましたら、公式のdocを読んでみてください。
参考資料
Official doc: https://recoiljs.org/Using Recoil instead of Redux For State Management In React Applications.: https://blog.openreplay.com/using-recoil-instead-of-redux-for-state-management-in-react-applications
How to Use Recoil for State Management in Your React Projects
https://www.freecodecamp.org/news/how-to-use-recoil-for-state-management-in-your-react-projects/
Understand Recoil in React: https://www.telerik.com/blogs/recoil-in-react
Reactの実験的ステート管理ライブラリRecoilの基本的な使い方: https://sbfl.net/blog/2020/05/17/react-experimental-recoil-usage/
Facebook製の新しいステート管理ライブラリ「Recoil」を最速で理解する: https://blog.uhy.ooo/entry/2020-05-16/recoil-first-impression/
ここまでお読みいただき、ありがとうございました!