今回は少し LWC の中身に踏み込んで、LWC のデータサービスについて調べてみました。
@wire
デコレータの使い方や仕組みをより深く理解したい方や、カスタムワイヤーアダプターを作成してみたい方向けです。
##LWC が提供するデータサービス
LWC の RFC には、 LWC がフレームワークとして提供すべきデータサービスの規約が明記されています。その中には以下のような内容が含まれています。
- データを扱う LWC はランタイムでも高速に動作する事
- LWC の開発とライフサイクルが簡潔である事
- Aura と LWC のデータサービスに互換性がある事
- キャッシュされているデータと表示されているデータに一貫性が保たれている事
これらの規約に則り、LWC ではデータサービスとして LWC コンポーネントがデータを取得するための仕組みである「ワイヤーサービス」を提供しています。
##ワイヤーサービス
ワイヤーサービスとは、LWC コンポーネントとデータソースを宣言的につなげる仕組みのことで @lwc/wire-service パッケージとして公開されています。開発者は、@wire
デコレータによりデータの取得を宣言的に行えるようになります。
@wire(getRecord, { id: '$recordId' }) record;
@wire
デコレータは以下の形式で宣言されます。
@wire(adapterId, [adapterConfig]) wiredProperty|wiredMethod;
// adapterId: データの取得、管理、プロビジョンする関数の識別子
// adapterConfig: (省略可)オブジェクト型のアダプター設定情報
// wiredProperty|wiredMethod: プロビジョンされる変数、もしくは関数
##ワイヤーアダプター
ワイヤーアダプターとは、ワイヤーサービスによって呼び出され、データの取得、管理、プロビジョンを行うのプラグイン関数です。
Lightning プラットフォーム上で動作する LWC コンポーネントの場合、lightning/ui*Api Wire Adapters and Functions にあるワイヤーアダプターが利用可能ですが、オープンソース版 LWC コンポーネントではカスタムワイヤーアダプターを作成する必要があります。
##カスタムワイヤーアダプターの実装サンプル
ワイヤーサービスを利用しデータを取得する場合、独自のワイヤーアダプターを作成する事ができます。salesforce/lwc にはカスタムワイヤーアダプターの作成例が含まれています。以下はその一部抜粋と説明を追加したものです。
import { register, ValueChangedEvent } from 'wire-service';
import getObservable from './todo';
// データを取得する関数の実装
// 通常は XHR や Fetch API によりサーバーからデータを取得する処理を記述する
// 必ず Promise を返し、resolve/reject する値は読み取り専用 Proxy とする
export function getTodo(config) {
return new Promise((resolve, reject) => {
const observable = getObservable(config);
...
observable.subscribe({
next: value => resolve(value),
...
});
});
}
// getTodo をワイヤーアダプターとして登録する事で、@wire(getTodo) 出来るようになる。
// 引数の wiredEventTarget には 3 つのイベントが発生するため適宜データを取得/再取得する
// - config: @wire の adapterConfig に変更が発生した時
// - connect: コンポーネントが接続した時
// - disconnect: コンポーネントが切断された時
// データを取得した際、ValueChangedEvent を発火する事で、
// wiredProperty もしくは wiredMethod をプロビジョンしてくれる
register(getTodo, function getTodoWireAdapter(wiredEventTarget) {
let subscription;
let config;
wiredEventTarget.dispatchEvent(new ValueChangedEvent({ data: undefined, error: undefined }));
const observer = {
next: data =>
wiredEventTarget.dispatchEvent(new ValueChangedEvent({ data, error: undefined })),
...
};
wiredEventTarget.addEventListener('connect', () => {
const observable = getObservable(config);
if (observable) {
subscription = observable.subscribe(observer);
}
});
wiredEventTarget.addEventListener('disconnect', () => {
subscription.unsubscribe();
});
wiredEventTarget.addEventListener('config', newConfig => {
config = newConfig; // リアクティブプロパティは値として解決済み
...
const observable = getObservable(config);
if (observable) {
subscription = observable.subscribe(observer);
}
});
});
##カスタムワイヤーアダプターの実装サンプルを動かしてみる
カスタムワイヤーアダプターの実装サンプルは、ローカルサーバーで実行出来る形で公開されているので、クローンすれば実際に動作を確認する事が出来ます。
#####動作環境の確認
- Github からソースを取得後にビルドする必要があるのですが、バージョンに制約があります。以下は私が動作確認したバージョンです。
$ node -v
> 10.16.0
$ npm -v
> 6.9.0
$ yarn -v
> 1.17.3
#####ソースコードの取得とビルド
- まずはリポジトリ全体をクローンし、LWC をビルドします。
$ git clone https://github.com/salesforce/lwc.git
$ cd lwc
$ yarn
#####カスタムワイヤーアダプターの動作を確認
- ワイヤーサービスのパッケージ内にカスタムワイヤーアダプターのサンプルがあるので、ローカル環境で動作させてみます。
$ cd packages/@lwc/wire-service
$ yarn start
$ open http://localhost:3000
- ブラウザに表示されるのはこんな画面
-
Load a todo by id
の値を変更すると、その変更に応じて表示内容が変わります。 - カスタムワイヤーアダプターに対し複数パターンの呼び出しサンプルがあるため、それぞれの動作を比較出来ます。
-
##参考