この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
以前のエントリでReactでGlobalに状態管理を行う方法としてuseContextを試してみました。
他方で「Reactで状態管理を行うならRecoilが便利だよ」というアドバイスをもらっていたので、今回はRecoilへの入門として公式のGetting StartedをTSプロジェクトで試してみました。
やってみる
こちらのGetting Startedを参考にRecoilをTSプロジェクトで動かしてみます。
Reactアプリの準備
create-react-app
でReactアプリをTSプロジェクトで作成します。
$ npx create-react-app web --template typescript
$ cd web
これにより次のようなバージョンでReactアプリが作成できました。
- react@18.0.0
- typescript@4.6.3
インストール
Recoilをインストールします。
$ npm install recoil
まず動かしてみる
まず動くデモを作ってみます。src/App.tsx
を次のように修正します。
src/App.tsx
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
export default App;
const textState = atom({
key: 'textState', // unique ID (with respect to other atoms/selectors)
default: '', // default value (aka initial value)
});
function CharacterCounter() {
return (
<div>
<TextInput />
<CharacterCount />
</div>
);
}
function TextInput() {
const [text, setText] = useRecoilState(textState);
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setText(event.target.value);
};
return (
<div>
<input type='text' value={text} onChange={onChange} />
<br />
Echo: {text}
</div>
);
}
const charCountState = selector({
key: 'charCountState', // unique ID (with respect to other atoms/selectors)
get: ({ get }) => {
const text = get(textState);
return text.length;
},
});
function CharacterCount() {
const count = useRecoilValue(charCountState);
return <>Character Count: {count}</>;
}
Reactアプリを実行します。
$ npm start
ブラウザでアプリが起動します。入力欄に文字を入力すると、入力した文字とカウントが表示される仕組みが作れました。
コード解説
RecoilRoot
Recoilによる状態管理を行いたいComponent treeの親をRecoilRootでラップする必要があります。
src/App.tsx
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
ポイントとして、ラップ時にその子Component内で使用したい状態やその値を指定する必要はありません。(useContextの場合は指定する必要がありました。)
Atom
Recoilではatom
で作成したRecoilStateを状態として使用します。
src/App.tsx
const textState = atom({
key: 'textState', // unique ID (with respect to other atoms/selectors)
default: '', // default value (aka initial value)
});
RecoilStateはuseRecoilState
を使用して読み書きを行うHooksです。
src/App.tsx
function TextInput() {
const [text, setText] = useRecoilState(textState);
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setText(event.target.value);
};
return (
<div>
<input type='text' value={text} onChange={onChange} />
<br />
Echo: {text}
</div>
);
}
状態の読み書きを組み込み関数で行えるのは便利ですね!
Selector
selector
を使用するとRecoilStateを変換した値を取得できるRecoilValueReadOnlyを作成できます。
src/App.tsx
const charCountState = selector({
key: 'charCountState', // unique ID (with respect to other atoms/selectors)
get: ({ get }) => {
const text = get(textState);
return text.length;
},
});
RecoilValueReadOnlyからはuseRecoilValue
を使用して値を読み取ることができます。
src/App.tsx
function CharacterCount() {
const count = useRecoilValue(charCountState);
return <>Character Count: {count}</>;
}
状態管理対象の値を変換して使用することが多い場合に役立ちそうです。
おわりに
RecoilのGetting StartedをTSプロジェクトで試してみました。
Reactの組み込みHooksであるuseContextと比べ、少ない記述でより簡単に状態管理が行えるという印象でした。
注意点として、2022年4月現在、Recoilはexperimentalとなっています。Repositoryのホストもまだfacebookexperimental
で行われています。
2020年6月にMeta社により開発が開始され、現在v0.7.0
なのでGAまでもう一息というところでしょうか。GAが待ち遠しいですね。
参考
以上