メインコンテンツへスキップ

Loadableクラス

Loadableオブジェクトは、Recoilのatomまたはselectorの現在の状態を表します。この状態は、値が利用可能であるか、エラー状態であるか、非同期解決がまだ保留中であるかのいずれかです。Loadableは次のインターフェースを持ちます。

  • state: atomまたはselectorの現在の状態。可能な値は'hasValue''hasError'、または'loading'です。
  • contents: このLoadableによって表される値。状態がhasValueの場合、実際の値です。状態がhasErrorの場合、スローされたErrorオブジェクトです。状態がloadingの場合、値のPromiseです。

Loadableには、現在の状態にアクセスするためのヘルパーメソッドも含まれています。 *このAPIは不安定であるとみなしてください*

  • getValue() - React SuspenseとRecoil selectorのセマンティクスに一致する値にアクセスするためのメソッド。状態に値がある場合、値を返します。エラーがある場合、そのエラーをスローします。保留中の場合、保留中の状態を伝播するために実行またはレンダリングを中断します。
  • toPromise(): selectorが解決されたときに解決されるPromiseを返します。selectorが同期しているか、既に解決している場合、すぐに解決されるPromiseを返します。
  • valueMaybe() - 利用可能な場合に値を返し、それ以外の場合はundefinedを返します。
  • valueOrThrow() - 利用可能な場合に値を返し、そうでない場合はErrorをスローします。
  • map(callback) - Loadableの値を変換する関数を取り、変換された値を持つ新しいLoadableを返します。変換関数は親Loadableの値のパラメータを取得し、新しいLoadableの新しい値を返すことができます。また、スローされたエラーまたはサスペンスも伝播します。コールバック関数は、新しい値、新しい値のPromiseまたはLoadableを返すか、エラーをスローすることができます。このメソッドは、Promiseの.then()と比較できます。

function UserInfo({userID}) {
const userNameLoadable = useRecoilValueLoadable(userNameQuery(userID));
switch (userNameLoadable.state) {
case 'hasValue':
return <div>{userNameLoadable.contents}</div>;
case 'loading':
return <div>Loading...</div>;
case 'hasError':
throw userNameLoadable.contents;
}
}

Loadableの作成

独自のLoadableオブジェクトを作成するには、RecoilLoadableインターフェースをインポートできます。

interface RecoilLoadable {
function of<T>(T | Promise<T>, Loadable<T>): Loadable<T>;
function error<T>(mixed): Loadable<T>;
function all(Array<mixed | Loadable<mixed> | Promise<mixed>>): Loadable<Array<mixed>>;
function all({[string]: mixed | Loadable<mixed> | Promise<mixed>}): Loadable<{[string]: mixed}>;
function loading(): Loadable<empty>;
function isLoadable(mixed): boolean;
}

RecoilLoadable.of(123);

RecoilLoadable.error(new Error('ERROR'));

RecoilLoadable.all([
RecoilLoadable.of(1),
RecoilLoadable.of(10),
RecoilLoadable.of(100),
]).map(([a, b, c]) => a+b+c);

Loadableは非同期値を表す場合があります。

// Asynchronously resolves to 123
RecoilLoadable.of(Promise.resolve(123));

Promise.resolve()と同様に、RecoilLoadable.of()は、アンパックされるLoadableやPromiseだけでなく、リテラル値も受け入れることができます。

// All resolve to 'x'
RecoilLoadable.of('x');
RecoilLoadable.of(RecoilLoadable.of('x'));
RecoilLoadable.of(Promise.resolve('x'));

同様に、Promise.all()と同様に、RecoilLoadable.all()は、Loadable、Promise、またはリテラル値の配列を受け入れることができます。

// Resolves to [1, 2, 3]
RecoilLoadable.all([1, RecoilLoadable.of(2), Promise.resolve(3)]);

// Resolves to {value: 1, loadable: 2, promise: 3}
RecoilLoadable.all({
value: 1,
loadable: RecoilLoadable.of(2),
promise: Promise.resolve(3),
});

// Never resolves
RecoilLoadable.loading();