
ReactアプリケーションでWebコンポーネントを使用する
所要時間:8 分
前回の記事 前の記事では、Web コンポーネントをビルドして公開する方法を紹介しました。
さて、次はWeb Componentsのトップ機能の使い方です:
ウェブコンポーネントの標準に基づいて構築されたカスタムコンポーネントやウィジェットは、モダンブラウザで動作し、HTMLで動作するJavaScriptライブラリやフレームワークで使用することができます。
この記事では、Webコンポーネントをどのように Reactアプリケーションにどのように統合できるかを見ていきます。
Vonage API アカウント
ウェブコンポーネント
まず、アプリケーションで使われるウェブ・コンポーネントを見てみましょう。
キーパッドのコンポーネントは 前の記事と連絡先リスト・コンポーネントがある。連絡先リストは、ブラウザのローカル・ストレージから呼び出された人の名前と電話番号を保存したり読み込んだりすることができます。 ローカルストレージ.ウェブコンポーネントは、クリックされたときにカスタムイベントとして連絡先の電話番号をアプリケーションに出力することもできます。
また マテリアルウェブコンポーネントダイアログダイアログもあり、通話終了後にその番号がまだ連絡先に登録されていなければ表示されるので、保存することができる。

課題
ReactアプリケーションでこれらのWeb Componentsを使用する際に、どのようなハードルにぶつかるかを確認するために、以下を参照する。 どこでもカスタム要素.
彼らは、「フレームワークとカスタム・エレメントが仲良しになれるようにする🍻」という崇高な責任を担っている。
これは、フレームワークやライブラリをさまざまなテストにかけ、ウェブ・コンポーネントとどの程度統合できるかを報告することで達成される。
では、リアクトはどうなのだろうか?この記事を公開した時点での結果は以下の通りだ:

見た目は良くないが、何とかなるだろう。いくつかの問題点を見てみよう。
Web コンポーネントにデータを渡す方法のひとつに、プロパティがあります:
<dwanes-keypad actionText="Call" cancelText="Hang up"></dwanes-keypad>
Reactアプリケーションでこれを行うと、データは文字列化される。そのため、配列(例えば[1,2,3,4])を渡すと "1,2,3,4 "となり、オブジェクト(例えば{"key1":value1, "key2":value2})を渡すと"[object Object]"となります。
もう一つの問題は がイベントを処理する方法です。.
Reactには SyntheticEventインスタンスを持っている。Custom Elements Everywhereの調査結果によると、ReactのSyntheticEventは「カスタム要素から来るDOMイベントをリッスンすることができない」。また、次に紹介する解決策も提供している。
ソリューション
何が待ち構えているのか分かったところで、これらの問題を克服するために努力しよう。
基本的なReactの「App」コンポーネントを作成し、その中にウェブ・コンポーネントを配置する計画だ。
Reactアプリケーションでコンポーネントを記述するには、次の2つの方法があります。 クラスまたは関数.
以前は、コンポーネントで「ステート」を使用する必要があるかどうかが、次のようなコンポーネントを使用するかどうかの決定要因でした。 関数コンポーネントよりもクラスコンポーネント.
そしてReact 16.8では フックが導入された。"クラスを書かずにステートや他のReactの機能を使うことができる。"
そこで、この記事ではできるだけ徹底して、クラス・コンポーネントとフック付き関数コンポーネントを使用して作成されたReactアプリケーションのWeb Componentsも含めて説明します。
Web Componentsを使用するときと同様に、プロジェクトに含める必要があります。インストールするか、CDNからリンクすることができます。(これは 前の記事.)
この統合では、CDNからプルする。
タグの <head>タグの public\index.htmlファイルの中にある:
<!-- Web Component polyfill -->
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
<!-- Load the Web Components -->
<script type="module" src="https://unpkg.com/@material/mwc-dialog@canary/mwc-dialog?module"></script>
<script type="module" src="https://unpkg.com/@dwane-vonage/dwanes-keypad@latest/dwanes-keypad.js?module"></script>
<script type="module" src="https://unpkg.com/@dwane-vonage/dwanes-contacts@latest/dwanes-contacts.js?module"></script> クラス・コンポーネント
サンプルコードは グリッチ・プロジェクト.
注:私は グリッチ・リアクト・スターター・テンプレート.
イベントの処理
ウェブ・コンポーネントからのイベントを処理できるようにするには、まずそのコンポーネントへの参照を取得し、Reactがそのコンポーネントの存在を認識し、イベント・リスナーを追加できるようにする必要があります。イベントリスナーを追加するには src\App.jsrender関数の中で refタグがあります:
<main>
<section>
<dwanes-keypad actionText="Call" cancelText="Hang up" ref="keypad"></dwanes-keypad>
<div id="status">{this.state.callStatus}</div>
</section>
<dwanes-contacts ref="contacts"></dwanes-contacts>
</main>
<mwc-dialog id="dialog" heading="Contacts" ref="dialog">
<p>Save <span id="number-to-save">{this.state.numberToSave}</span> to contacts?</p>
<mwc-textfield
id="text-field"
minlength="3"
maxlength="64"
placeholder="First name"
dialogInitialFocus
required
ref="firstName">
</mwc-textfield>
<mwc-button
id="primary-action-button"
slot="primaryAction"
onClick={this.handleSaveContact}>
Confirm
</mwc-button>
<mwc-button
slot="secondaryAction"
dialogAction="close">
Cancel
</mwc-button>
</mwc-dialog>
タグは refタグはReactにこれらの要素に注意を払うように知らせる。
での componentDidMount()で src\App.jsで、先ほど設定した要素参照にイベント・リスナーが追加されます。以下がそのコードだ:
this.refs.contacts.addEventListener('contacts-loaded', (event) => {
contacts = event.detail.contacts;
console.log('contacts-loaded: ', contacts);
});
this.refs.contacts.addEventListener('contact-selected', (event) => {
this.refs.keypad.setDigits(event.detail.contact.phone);
});
this.refs.keypad.addEventListener('action-ended', () => {
this.setState({callStatus: "Call has ended."});
const contactFound = contacts.find(contact => contact.phone === this.state.numberToSave);
if (contactFound){
console.log('Number already in contacts')
} else {
this.refs.dialog.show();
}
});
this.refs.keypad.addEventListener('digits-sent', event => {
if (event.detail.digits !== ""){
this.refs.keypad.createAction();
this.setState({callStatus: "Call is being made", numberToSave:event.detail.digits});
} else {
this.setState({callStatus: "Please enter a phone number."});
}
});
this.refs.keypad.addEventListener("digit-added", event => {
console.log('digit-added: ', event.detail.digit);
});
データの取り扱い
キーパッド・コンポーネントの場合、プロパティに文字列を渡しているので、Reactではそのデータに対して特別な処理をする必要はない。
通話後にコンタクトを保存する場合、データはオブジェクトです:
{name:this.refs.firstName.value, phone:this.state.numberToSave}これは、連絡先リストWebコンポーネントのメソッドに渡されます:
this.refs.contacts.saveContact({name:this.refs.firstName.value, phone:this.state.numberToSave});連絡先リスト・コンポーネントが、データを操作してローカル・ストレージに保存するためにオブジェクトを使用していない場合、次のようにオブジェクトを渡すことができる:
this.refs.contacts.contactProp = {name:this.refs.firstName.value, phone:this.state.numberToSave};配列についても同様である。
重要なお知らせです!ウェブ・コンポーネントへの参照を取得するために使用されたAPIはレガシーとみなされ、「将来のリリースのいずれかで削除される可能性があります。 ドキュメントに詳細と代替方法があります。
その選択肢のひとつを紹介しよう。
React 16.3以降を使用している場合は、Glitch Projectを参照してください。 サンプルコードを使用して React.createRef().
構文が増えただけで、考え方はほとんど同じだ。コンストラクタで React.createRef()で参照を作成します:
this.contacts = React.createRef();でウェブ・コンポーネントにアタッチする。 render:
<dwanes-contacts ref={this.contacts}></dwanes-contacts>
にイベントリスナーを追加する。 componentDidMount():
this.contacts.current.addEventListener('contact-selected', (event) => {
this.keypad.current.setDigits(event.detail.contact.phone);
});
Webコンポーネントのメソッドを呼び出す:
this.contacts.current.saveContact({name:this.firstName.current.value, phone:this.state.numberToSave});リッチ」なデータをウェブコンポーネントに渡します:
this.contacts.current.contactProp = {name:this.firstName.current.value, phone:this.state.numberToSave};
this.contacts.current.arrayProp = [value1, value2, value3]; フック付き関数コンポーネント
さて、React 16.8の最新版では、Web Componentの参照を作成するために使用できます。
重い作業の多くはフックで処理される。ステートの処理であれ、副作用であれ、DOMの参照であれ、おそらく使えるフックがあるはずだ。
そうでない場合は、カスタムフックを作ることができる。
この場合、使用するフックのひとつは useRef.
これは React.createRef()例
フック付きファンクションコンポーネントのサンプルコードは、次のページにあります。 Glitch プロジェクト.
イベントの処理
まず、各Webコンポーネントの参照を初期化する必要があります。これは次のコードで行う:
const keypad = useRef(null);
const dialog = useRef(null);
const contactsEl = useRef(null);
const firstName = useRef(null);nullはリファレンスの初期値。
次に、リターンセクションで、ウェブコンポーネントへの参照を ref={referenceName}.
これがコードだ:
<main>
<section>
<dwanes-keypad actionText="Call" cancelText="Hang up" ref={keypad}></dwanes-keypad>
<div id="status">{callStatus}</div>
</section>
<dwanes-contacts ref={contactsEl}></dwanes-contacts>
</main>
<mwc-dialog id="dialog" heading="Contacts" ref={dialog}>
<p>Save <span id="number-to-save">{numberToSave}</span> to contacts?</p>
<mwc-textfield
id="text-field"
minlength="3"
maxlength="64"
placeholder="First name"
dialogInitialFocus
required
ref={firstName}>
</mwc-textfield>
<mwc-button
id="primary-action-button"
slot="primaryAction"
onClick={handleSaveContact}>
Confirm
</mwc-button>
<mwc-button
slot="secondaryAction"
dialogAction="close">
Cancel
</mwc-button>
</mwc-dialog>
それでは、イベント・リスナーを追加しよう。
このため、それらを を使用する。:
useEffect(()=> {
contactsEl.current.addEventListener('contacts-loaded', handleContactsLoaded);
contactsEl.current.addEventListener('contact-selected', handleContactSelected);
keypad.current.addEventListener('digit-added', handleDigitAdded);
keypad.current.addEventListener('digits-sent', handleDigitsSent);
keypad.current.addEventListener('action-ended', handleActionEnded);
return () => {
contactsEl.current.removeEventListener('contacts-loaded', handleContactsLoaded);
contactsEl.current.removeEventListener('contact-selected', handleContactSelected);
keypad.current.removeEventListener('digit-added', handleDigitAdded);
keypad.current.removeEventListener('digits-sent', handleDigitsSent);
keypad.current.removeEventListener('action-ended', handleActionEnded);
};
});
データの取り扱い
前述したように、これはサンプル・コードの React.createRef()サンプルコードに非常に似ている。
ウェブコンポーネントのメソッドを使用してデータを送信します:
contactsEl.current.saveContact({name:firstName.current.value, phone:numberToSave});リッチ」なデータをウェブコンポーネントに渡す:
contactsEl.current.contactProp = {name:this.firstName.current.value, phone:this.state.numberToSave};
contactsEl.current.arrayProp = [value1, value2, value3]; 電話をかける
ウェブ・コンポーネントの準備は整ったので、Reactアプリケーションに電話をかけてみよう。
以下の手順は、アプリ内で音声通話をする手順を修正したものです。 チュートリアルを修正したものです。
より詳細については、そちらを参照してほしい。
これを作動させるには
ネクスモCLI
GitHubアカウント
ステップ1:リミックス グリッチプロジェクト.
これにより、ReactアプリケーションとWeb Componentsがセットアップされるだけでなく、Nexmo Client SDKもインストールされます。 NexmoクライアントSDKをインストールします。
ステップ2:Nexmo CLIツールをインストールします。
ターミナルで
ダッシュボードからVonage Developer API KeyとAPI Secretを取得します。 ダッシュボード.
ターミナルで以下のコマンドを実行し、api_keyとapi_secretを自分のものに置き換える:
ステップ3:NCCOを作成する NCCOの作成.
にログインしていることを確認してください。 にログインしていることを確認してください。にログインしていることを確認し、https://gist.github.com にアクセスします。
を入力してください。 ncco.jsonを「拡張子を含むファイル名」に入力する。
以下のJSONオブジェクトをコピーしてgistに貼り付ける:
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"endpoint": [
{
"type": "phone",
"number": "PHONE_NUMBER"
}
]
}
]置き換える PHONE_NUMBERを電話番号に置き換えてください。Nexmoの番号はE.164形式で、"+"や"-"は無効です。電話番号を入力する際は、必ず国番号を指定してください:14155550100、UK:447700900001.
ボタンをクリックする。 Create secret gistボタンをクリックする。
ボタンをクリックする。 Rawボタンをクリックする。
ブラウザに表示されたURLをメモしておいてください。
ステップ4:Nexmoアプリケーションを作成する
まだプロジェクト・ディレクトリを作成していない場合は、作成してください。
プロジェクト・ディレクトリに移動する。
以下のコマンドをターミナルにコピー&ペーストして、Nexmoアプリケーションを作成します:
引数の
--voice-answer-url引数のGIST-URLに置き換えてください。
プロジェクトディレクトリに .nexmo-appという名前のファイルがプロジェクトディレクトリに作成され、新しく作成されたNexmoアプリケーションIDと秘密鍵が含まれます。という名前の秘密鍵ファイルも作成されます。 private.keyという名前の秘密鍵ファイルも作成されます。
アプリケーションIDは今後必要になりますので、メモしておいてください。
ステップ5:ユーザーを作成する
Nexmo CLIを使用して、以下のコマンドでAliceというユーザーを作成します:
これにより、以下のようなユーザーIDが返される:
User created: USR-aaaaaaaa-bbbb-cccc-dddd-0123456789ab
ステップ6:JWTを生成する
以下のコマンドを実行して、Nexmo CLIを使用してJWTを生成します。 APP_ID変数を独自の値に置き換えることを忘れないでください:
生成されたJWTは今後6時間有効である。
JWTをコピーして src/App.jsGlitchプロジェクトファイルの「PASTE ALICE JWT HERE」と書いてあるところにペーストしてください。
ステップ7:自分に電話する!
キーパッドで番号をダイヤルし コール.
すべてが正しく機能していれば、電話がかかってくるはずです。通話が終了すると、番号を保存するかどうかを尋ねるダイアログボックスがポップアップ表示されるはずです。
注:NCCOはあなたの電話番号でハードコードされているので、キーパッドで入力されたものに関係なく、あなたの番号が呼び出されます。NCCOを動的に生成するには、バックエンドで行う必要があります。
さて、これで終わりです!これでReactアプリケーションでWeb Componentsを使うことができました。
うまくいったか?クールだったか?
コーディングでは何でもそうだが、物事には複数のやり方がある。
もう一つの方法は リアクトと ステンシルJSのドキュメントで見つけた別の方法は、Web ComponentsをReact Componentsでラップすることです。
そのような方法、あるいは別の方法はありますか?それについて、あるいはその他のコメントや質問について、私たちの コミュニティ・スラック・チャンネル.