チーム開発でRecoilを良い感じに使う(ベストプラクティス?)
はじめに
今回は「俺が考えた最強のRecoilの使い方」を紹介します
Recoilのベストプラクティスを紹介する記事が見当たらなかったので書いてみました
既出でしたら申し訳ありません
間違いや改善点、疑問点等ありましたら是非コメントでご指摘ください
注意
本記事はRecoil修得済みの方向けの記事になります
Recoilなんもわからんな方は是非以下の記事をご覧ください(Recoilはいいぞ)
1.サンプルアプリ
今回は数字を保存する状態hogeState
を加工したhogeStrState
を表示するアプリを例にとります
create-react-appを使用して作成したプロジェクトです
左右のボタンによりインクリメント・デクリメントが可能
2.ディレクトリ構成
src
├── components
~省略~
└── recoil
├── {State名}
| ├── index.ts
| ├── states.ts
| ├── (types.ts)
| └── {Module名}.ts
└── recoilKeys.ts
※ State名 = {Key}State
※ Module名 = {State名(先頭大文字)}Module
3.Keyの管理
まずはKey(atom等のプロパティであるkey
)の管理です
重複が許されないKeyはrecoilKeys.ts
で一元管理します
配列のままだと使用時にindexを指定しなければいけなくなるので、Key: Key
のオブジェクトに加工してexportしています
// Keyの配列
const recoilKeys = [
"hoge",
"hogeStr",
"fuga",
"piyo",
] as const
// Key: Keyのオブジェクト
export const recoilKeyHashSet = Object.fromEntries(
recoilKeys.map((k) => [k, k])
) as {
[k in typeof recoilKeys[number]]: k;
};
// 重複チェック
const set = new Set(recoilKeys);
if (set.size !== recoilKeys.length) {
throw Error("recoilKeyが重複しています");
}
4.ディレクトリ構成の詳細と実装
状態の配置
src
├── components
~省略~
└── recoil
├── hogeState
└── recoilKeys.ts
State(atom, selector等状態の総称)はsrc/recoil/
直下にフォルダを作り実装します
この時依存関係があるStateは同じディレクトリに纏めます
そのためrecoil/atom/hogeState
、recoil/selector/hogeStrState
といったようなディレクトリ分けは不要になります
状態の実装
hogeState
├── index.ts
├── states.ts
├── (types.ts)
└── HogeStateModule.ts
index.ts
ルーターみたいなものです
import文を綺麗にするため纏めてexportします
export * from "./state"
export * from "./HogeStateModule"
states.ts
atom等を作成しexportします
加工した値を提供したい時はselectorを作成しexportしましょう
型が複雑な場合、types.ts
に型定義を移すといいかもしれません
export const hogeState = atom<number>({
key: recoilKeyHashSet.hoge,
default: 0
});
export const hogeStrState = selector<string>({
key: recoilKeyHashSet.hogeStr,
get: ({get}) => ` hogeState: ${get(hogeState)} `
});
(types.ts)
Stateに関する型を定義します
HogeStateModule.ts
関連する全てのStateの書き込み関数を提供するModuleを作成します
Stateが意図しない変更を防ぎ、実装を集約する意図です
モジュール名は、対象のState群の中でメインのStateのState名(先頭大文字)+ Module、と命名します
コンポーネント外でStateを変更するため、Recoil Nexusというライブラリを使用します
export const HogeStateModule = {
increment: () => setRecoil(hogeState, (pre) => pre + 1),
decrement: () => setRecoil(hogeState, (pre => pre - 1))
}
5.使用
StateはuseRecoilValue
・getRecoil
などの関数を使い取得します
import {HogeStateModule, hogeStrState} from './recoil/hogeState';
function App() {
const hogeStr = useRecoilValue(hogeStrState);
return (
<div className="App">
<header className="App-header">
<button onClick={HogeStateModule.decrement}>-</button>
{hogeStr}
<button onClick={HogeStateModule.increment}>+</button>
</header>
</div>
);
}
6.おわりに
チーム開発でRecoilを使う時のベストプラクティス?でした
今見返すと、一元的に管理することに重点を置いてることに気付きました
皆様のRecoilライフがより快適になれば嬉しいです
最後までお読み頂きありがとうございました!!
Discussion
記事ありがとうございます!
個人的な見解をこちらでまとめてみました、参考になれば幸いです。