はじめに
今回はReactの状態管理ライブラリRecoilについて紹介したいと思います。
A state management library for React
インストール
$ npm install recoil
or
$ yarn add recoil
or
$ bower install --save recoil
概要
Recoilを利用するにあたってAtomとSelectorの2つの概念を理解することがとても重要です。
Recoil lets you create a data-flow graph that flows from atoms (shared state) through selectors (pure functions) and down into your React components. Atoms are units of state that components can subscribe to. Selectors transform this state either synchronously or asynchronously.
// DeepL翻訳
Recoilでは、アトム(共有状態)からセレクタ(純粋関数)を経て、Reactコンポーネントに流れるデータフローグラフを作成することができます。アトムは、コンポーネントがサブスクライブすることができる状態の単位です。セレクタは、この状態を同期または非同期で変換します。
最初にそれぞれの説明を公式ドキュメントから引っ張ってきますが、使い方を見た方がより理解が深まると思います。
Atom
Atomにて共有したい状態を定義することができます。
An atom represents a piece of state. Atoms can be read from and written to from any component. Components that read the value of an atom are implicitly subscribed to that atom, so any atom updates will result in a re-render of all components subscribed to that atom:
// DeepL翻訳
アトムは、状態の一部を表します。アトムは、どのコンポーネントからも読み取ったり書き込んだりすることができます。アトムの値を読み取るコンポーネントは、暗黙のうちにそのアトムを購読しているため、アトムの更新は、そのアトムを購読しているすべてのコンポーネントの再レンダリングにつながります
Selector
Selectorを用いることでAtomの状態を利用して何らかの変換をした後の状態を読み込ませたり、何らかの変換をした後の状態をAtomに書き込むことができます。Selectorが純粋関数(入出力が一意に決定される関数)であることが大きな特徴です。
A selector represents a piece of derived state. Derived state is a transformation of state. You can think of derived state as the output of passing state to a pure function that modifies the given state in some way:
セレクタは、派生状態の一部を表します。派生状態とは、状態の変換のことです。派生状態は、与えられた状態を何らかの方法で変更する純粋な関数に状態を渡したときの出力と考えることができます
使い方
RecoilRootで囲う
Recoilを利用するにはまずRecoilRootというコンポーネントで囲ってあげる必要があります。
import { RecoilRoot } from 'recoil' function App() { return ( <RecoilRoot> <SampleComponent /> </RecoilRoot> ); } export default App;
Atom作成
keyと初期値を設定してあげます。
import { atom } from "recoil"; export const sampleState = atom({ key: "Key", // 他のAtom, Selectorと被らない任意の文字列 default: 10, // 初期値 });
Atomの読み込み・書き込み
作成したAtomを読み込み・書き込むする場合はuseRecoilStateを利用します。イメージとしてはuseStateとほとんど変わりません。
import { useRecoilValue, useSetRecoilState } from "recoil"; import { sampleState, filterdSampleState } from "./sampleAtom"; export const SampleComponent = () => { const [sample, setSample] = useRecoilState(sampleState); const onClick = () => { setSample(sample + 1); }; return ( <div> <p>{sample}</p> <button onClick={onClick}>インクリメント</button> </div> ); };
また読み込みだけしたい場合はuseRecoilValue、書き込みだけしたい場合はuseSetRecoilStateを利用します。
// const [sample, setSample] = useRecoilState(sampleState); const sample = useRecoilValue(sampleState); const setSample = useSetRecoilState(sampleState);
Selector作成
Atomに格納されている状態をSelectorという名の純粋関数(入出力が一意に決まっている関数)に通して受け取るようにすることができます。
export const filterdSampleState = selector({ key: "Key2", get: ({ get }) => { const sample = get(sampleState); return sample * 2; }, });
これを受け取るときはAtomの場合と同じ要領で使うことができます。
const filterdSample = useRecoilValue(filterdSampleState);
また上記では読み込みだけでしたが、書き込む処理を追加することもできます。
export const filterdSampleState = selector({ key: "Key2", get: ({ get }) => { const sample = get(sampleState); return sample * 2; }, set: ({ set }, newValue) => { set(sampleState, newValue); }, });