メインコンテンツにスキップ
バージョン: v18.0.0

ライブフィールド

クライアントの状態とサーバーの状態の重要な違いの1つは、クライアントの状態が時間とともに変化するため、それらの変化をUIに反映する必要があることです。これに対処するために、Relayリゾルバーは@liveとしてマークされる機能をサポートしています。ライブリゾルバーは、現在の値をread()するメソッドと、値の変更をsubscribe()するメソッドを含むLiveState型のオブジェクトを返すことが期待されます。

この値が時間とともに変化すると、Relayはこのフィールドに依存するすべての派生フィールド(変更がカスケードする場合の推移的な依存関係を含む)を自動的に再計算し、この変更の結果として更新されたフィールドを読み取ったコンポーネント/サブスクライバーの更新を効率的にトリガーします。

@live

リゾルバーをライブとしてマークするには、リゾルバー定義に@liveドキュメントブロックタグを追加します。例えば

import type { LiveState } from 'relay-runtime';

/**
* @RelayResolver Query.counter: Int
* @live
*/
export function counter(): LiveState<number> {
return {
read: () => store.getState().counter,
subscribe: (callback) => {
return store.subscribe(callback);
},
};
}
注記

IDをモデルにマッピングするフィールドリゾルバーと強力なモデルリゾルバーの両方が、@liveとして注釈を付けることができます。

LiveState型

Live Resolverの戻り値の型は、LiveStateと呼ばれます。これらの概念に精通している場合、概念的にはオブザーバブルまたはシグナルに似ています。オブザーバブルとは異なり、LiveStateがサブスクライバーに更新を通知する場合、新しい値は含まれません。代わりに、サブスクライバー(Relay)はread()を呼び出して新しい値を取得することが期待されます。

過剰な通知(読み取り値が実際に変更されていない場合のサブスクリプション通知)はサポートされていますが、パフォーマンス上の理由から、LiveState値のプロバイダーは、変更についてRelayに通知する前に、値が実際に変更されたことを確認することをお勧めします。

LiveStateの型は次のように定義されます

export type LiveState<T> = {
/**
* Returns the current value of the live state.
*/
read(): T,
/**
* Subscribes to changes in the live state. The state provider should
* call the callback when the value of the live state changes.
*/
subscribe(cb: () => void): () => void,
};

LiveStateオブジェクトの作成

ほとんどの場合、リアクティブデータストアを読み取り、LiveStateオブジェクトを返すヘルパー関数を定義します。たとえば、Reduxストアの場合、特定のセレクターのLiveStateを公開するラッパーを記述することができます。

type Selector<T> = (state: State) => T;

function selectorAsLiveState<T>(selector: Selector<T>): LiveState<T> {
let currentValue = selector(store.getState());
return {
read: () => currentValue,
subscribe: (cb) => {
return store.subscribe(() => {
const newValue = selector(store.getState());
if (newValue === currentValue) {
return;
}
currentValue = newValue;
cb();
});
return unsubscribe;
},
};
}

このヘルパーを使用するLive Resolverは、次のようになります

/**
* @RelayResolver Query.counter: Int
* @live
*/
export function counter(): LiveState<number> {
return selectorAsLiveState(getCounter);
}

function getCounter(state) {
return state.counter;
}

バッチ処理

データレイヤーで状態が変化すると、1つの変更によって多くの@liveリゾルバーサブスクリプションに更新が通知される可能性があります。デフォルトでは、これらの更新ごとにRelayはどのコンポーネントを更新する必要があるかを判断するための作業を行う必要があります。これは、かなりの量の重複作業が発生する原因となる可能性があります。

可能な場合は、@liveリゾルバーへの更新をバッチ処理することをお勧めします。これは、状態の更新をRelayStoreインスタンスのbatchLiveStateUpdates()呼び出しでラップすることによって行うことができます。

Reduxストアでの一般的な使用法は次のようになります

const store = createStore(reducer);
const originalDispatch = store.dispatch;

function wrapped(action) {
relayStore.batchLiveStateUpdates(() => {
originalDispatch(action);
})
}

store.dispatch = wrapped;