1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

カスタムワイヤーアダプターを作ってみました

Posted at

この記事では、 オープンソース版 LWC でカスタムワイヤーアダプターを作成し、 @wire デコレータでデータプロビジョンする方法をご紹介します。
オープンソース版 LWC でカスタム Express サーバーの設定方法 で作成したプロジェクトを編集する前提となっています。

ワイヤーアダプター

LWC にはデータサービスとしてワイヤーサービスと呼ばれる、LWC コンポーネントで利用するデータを宣言的に取得するための仕組みが備わっています。
ワイヤーサービスを利用してデータを取得する場合は、ワイヤーアダプターをインスタンス化する必要があり、以下のフォーマットで宣言する事になります。

@wire(adapterId, [config]) wiredProperty|wiredFunction
// @wire: wire デコレータ。config の値に変更があれば wireAdapter に紐づく eventTarget に通知する
// adapterId: データ取得ロジックが実装されたアダプター関数への参照
// config: アダプターを起動する設定。通常はデータ取得のためのパラメータ。
// wiredProperty|wiredFunction: ワイヤー変数、もしくはワイヤー関数。ワイヤー値でプロビジョンされる。

開発者は独自のアダプターを開発し、wire でデコレートする事であらゆるワイヤーアダプターを作成する事が出来ます。

初めてワイヤーサービスを使う場合

オープンソース LWC で新規に作成したプロジェクトの場合、そのままではワイヤーサービスを利用できません。
ワイヤーサービスを使うには、lwc モジュールの register 関数と wire-service モジュールを紐付けておく必要があります。

src/client/index.js
import { createElement, register} from 'lwc';
import MyApp from 'my/app';

// register 関数を wire-service に登録する
import { registerWireService } from 'wire-service';
registerWireService(register);

const app = createElement('my-app', { is: MyApp });
document.querySelector('#main').appendChild(app);

カスタムワイヤーアダプターを使ったサンプル

このサンプルでは、画面上ので選んだ値をもとに、サーバーから顧客情報を取得、画面にテキストで表示する、というシンプルなコンポーネントを作成しています。

src/client/modules/my/app/app.html
<template>
    <select onchange={onSelectChanged}>
        <option value="1">1</option>
        <option value="2">2</option>
    </select>
    <p>{contact}</p>
</template>
src/client/modules/my/app/app.js
import {LightningElement, wire} from 'lwc';
import getContact from 'api/getContact';

// Component Class
export default class App extends LightningElement {
    // Private Properties
    contactId;

    // Wired Properties
    @wire(getContact, {contactId: '$contactId'}) _contact;

    // Getters and Setters
    get contact() { 
        return JSON.stringify(this._contact.data); 
    }

    // Callbacks
    renderedCallback() {
        const select = this.template.querySelector('select');
        this.contactId = select.options[select.selectedIndex].value;
    }

    // Event Handlers
    onSelectChanged(e) {
        this.contactId = e.target.value;
    }
}
src/client/modules/api/getContact/getContact.js
import { register, ValueChangedEvent } from 'wire-service';

// アダプターとなる関数を定義し、エクスポートする
export default function getContact(config) {
    if (!config.contactId) return Promise.resolve();
    return fetch(`/contact/${config.contactId}`).then(response => response.json());
}

// アダプター関数に紐づくワイヤーアダプターをインスタンス化するためのファクトリー関数を登録する
// ファクトリー関数では、いつ、どんな形式でワイヤー変数/関数をプロビジョンするかを定義しておく
register(getContact, eventTarget => {
    // コンポーネントが接続された時
    eventTarget.addEventListener('connect', () => {
        // ワイヤー変数/関数に初期値をプロビジョンする
        eventTarget.dispatchEvent(new ValueChangedEvent({ data: undefined, error: undefined }));
    });

    // config が変更された時
    eventTarget.addEventListener('config', config => {
        // 新しい config でワイヤー変数/関数をプロビジョンする
        getContact(config)
            .then(contact => eventTarget.dispatchEvent(new ValueChangedEvent({ data: contact })))
            .catch(error => eventTarget.dispatchEvent(new ValueChangedEvent({error: error})))
    });

    // コンポーネントが切断された時
    eventTarget.addEventListener('disconnect', config => {
        // 処理なし
    });
});
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?