Recoil 0.0.10リリース!バグが修正されて、新機能も追加!
2020年6月18日にRecoi最新版となるバージョン0.0.10がリリースされました。バージョン0.0.9も同日にリリースされましたが、新機能のRecoil SnapshotのHooksのメソッド名が変更されて、すぐに0.0.10としてリリースされました。これによりNext.jsのようなSSR(サーバサイドレンダリング)をするようなフレームワークで発生していた下記の不具合も無事に修正されました。
SSR時にRecoil version 0.0.8だとwindow is not definedのエラーになる
さらにRecoil SnapshotsやTypeScriptのサポートなども追加されて、さらに用途の幅が広がりました。 詳細はこちらになります。
Recoil バージョン 0.0.10の内容
不具合修正
- サーバサイドレンダリングに関する機能を修正。ただし、現時点では正式にはサポートしない。
- 特定のケースでSelectorが dependency subscriptionsを記録することを修正。
- 現時点のStateを取得するようにUpdaterを修正。
- オープンソースのビルドの際、特定のエラーを投げる時のエラーメッセージを修正。
- オープンソースのビルドの際、Flowエラーを減少。
改善
- ほとんどのRecoil hooksでatomやselectorを使用していない場合に、意味の分かるメッセージでエラーを投げる。
- テストの改善。
- オープンソースのビルドの改善。
TypeScriptのサポート
- APIとの同期を維持しやすくするために、DefinitelyTypedを使う代わりに、Recoil GitHubのリポジトリに置かれます。
- @Typeは下記のようにしてインストールできます。これで型定義を個人で管理する必要はなくなります。
npm install @types/recoil
# or
yarn add @types/recoil
Recoil Snapshot機能!
Recoil SnapshotはRecoilのatomのStateのイミュータブル(不変の)スナップショットです。これはグローバルなRecoilのStateやその派生するStateを観察、検査そして管理するためのAPIを標準化することを意図しています。開発ツールやグローバルな状態の動機、履歴機能、ナビゲーション機能の実装に役に立ちます。
Hooks
RecoilではSnapshotと機能する4つのHooksがあります。
- useRecoilSnapshot() - Snapshotへの同期アクセス
- useRecoilCallback() - Snapshotへの非同期アクセス
- useRecoilTransactionObserver() - 全てのStateの更新によるSnapshotをサブスクライブ
- useGotoRecoilSnapshot() - Snapshotに一致する現在のStateの更新
詳細はこちらになります。
動作確認
いくつかの実装例はGitHub上に上がっています。
次の実装は値の変化を捉えるためだけの簡単なコードです。
import React from "react";
import {
atom,
useRecoilState,
useRecoilTransactionObserver_UNSTABLE,
Snapshot,
useRecoilSnapshot,
} from "recoil";
const testState = atom({key: 'test', default: 0});
export const Test = () => {
const [test, setSet] = useRecoilState(languageState);
const currentSnapshot = useRecoilSnapshot();
// Store history data
const [history, setHistory] = React.useState({
past: [],
present: currentSnapshot,
});
// Get current value
console.log("currentSnapshot loadable", currentSnapshot.getLoadable(testState));
// If you need to use async, do as following.
// console.log(" + promise", currentSnapshot.getPromise(testState));
useRecoilTransactionObserver_UNSTABLE(({ snapshot, previousSnapshot }) => {
console.log("transaction current getLoadable", snapshot.getLoadable(testState));
//console.log(" + getPromise", snapshot.getPromise(languageState));
setHistory({
past: [...history.past, previousSnapshot],
present: snapshot,
});
});
return (
<div>
<p>{test}</p>
<button onClick={()=>setTest(test+1)}>increase</button>
</div>
)
}
画面が表示されると、コンソールに現在の値が出ます。 getLoadableで現在の値を同期的に取得できます。非同期の際は、getPromiseを使います。 結果はこのようになります。
currentSnapshot loadable {state: "hasValue", contents: "0", getValue: ƒ, toPromise: ƒ, valueMaybe: ƒ, ...}
画面でincreaseボタンを押すたびに、useRecoilTransactionObserver_UNSTABLEで変更がサブスクライブされているので、この中のコードが実行されます。 そこでも同じように現在の値とその前の値が取得できます。 これを例のようにhistoryとして管理しておくこともできます。
重要
Snapshotはグローバルです。使うときは注意しましょう。
まだまだできたばかりですし、unstableなコードもあるので、しばらくは様子見というのがよいでしょう。