2018年5月17日
プログラミング
Reactでスマートスピーカーのコマンド発音サービスを作ろう(3)【作りながら覚えるReact】


目次
はじめに
Reactで簡単なサービスを作りながら、使い方を覚えていくシリーズの第3弾です。
前回は、ReactでSmart Speaker’s Command Speaker(SSCS)のインタフェースを作り、部分的にコンポーネント化しました。
今回は実際に発音させていく部分を作ります。
発音させる
前回まで作っていたのがこちらです。
カードにコマンドはちゃんと表示されていますが、特にクリックすることもできず、また発音もしてくれません。
このカードをクリックしたらコマンドが発音される部分を作っていきましょう。
src/components/speaker_button.js
にまず、クリックイベントを作っていきます。
import React, { Component } from 'react';
export default class SpeakerButton extends Component {
_onClick() {
console.log("クリックされたよ");
}
render() {
return (
<div className="col-sm-6 mb-2 mt-2">
<button className="card" onClick={this._onClick}>
<div className="card-body">
<h4 className="card-title text-left">
<i className="fas fa-play"></i>
{this.props.speaker_type}音楽かけて
</h4>
<p className="card-text text-left">
ランダムで音楽をかけてくれるコマンドです。
</p>
</div>
</button>
</div>
);
}
}
まずこちらで_onClick()
を定義しています。
_onClick() {
console.log("クリックされたよ");
}
そしてこちらでボタンがクリックされたら、_onClickを実行しています。
<button className="card" onClick={this._onClick}>
ここまではシンプルですね。
では、実際に発音させてみます。
ブラウザ上で発音させる為には、SpeechSynthesisUtterance
という音声合成APIを使用します。
詳しくはMDNのリファレンスをご覧ください。
これだけで_onClickが実行されたらコマンドを発音してくれます。
_onClick() {
let ssu = new SpeechSynthesisUtterance();
ssu.text = "音楽かけて"
ssu.lang = 'ja-JP';
speechSynthesis.speak(ssu);
}
簡単に解説していきます。
let ssu = new SpeechSynthesisUtterance();
こちらでSpeechSynthesisUtterance
のインスタンスを作ります。
話す内容の設定をします。
ssu.text = "音楽かけて"
そして言語の設定をします。
ssu.lang = 'ja-JP';
最後に発音のコマンドを実行するだけです。
speechSynthesis.speak(ssu);
簡単ですね。
話す内容については、漢字でも正しく発音してくれますが、読み方次第では上手く発音してくれないので、場合によってはひらがなにしましょう。
これで、少しぎこちないですが「音楽かけて」とコマンドを発音してくれるようになりました。
Propsの値を使う
発音はできましたが、Alexaの場合には「アレクサ、」、Google Homeの場合には「OK, Google」とコマンド前につける必要があります。
なので、このコンポーネントのPropsの値を判定し、そこからコマンド前の「アレクサ、」「OK, Google、」という呼びかけ文言を発音してもらうようにしていきましょう。
src/app.js
上ではこのようにSpeakerButtonを使っていましたね。
<SpeakerButton speaker_type="alexa">
</SpeakerButton>
<SpeakerButton speaker_type="google">
</SpeakerButton>
そしてsrc/components/speaker_button.js
ではこのようにしてpropsの値を取り出していました。
this.props.speaker_type
これを利用して条件分岐していきましょう。
これでどうでしょうか。この先様々なスピーカーが出てくると考え、ifではなくswitchで条件を書いています。
_onClick() {
let ssu = new SpeechSynthesisUtterance();
let pre_commands = '';
switch (this.props.speaker_type) {
case 'alexa': {
pre_commands = "Alexa、";
break;
}
case 'google': {
pre_commands = "OK, Google、";
break;
}
default:
break;
}
ssu.text = `${pre_commands}音楽かけて`
ssu.lang = 'ja-JP';
speechSynthesis.speak(ssu);
}
POINT!!
`${pre_commands}音楽かけて` としているところは、JavaScriptのテンプレートリテラルを使用しています。
従来であれば pre_command + “音楽かけて” としなければいけなかったことを、すっきりとかけるようになっています。”#{pre_commands}音楽かけて” のように書くRubyなどの式展開と似ていますね。
さて、これでOKかと思いきや、このようなエラーが表示されます。
TypeError: Cannot read property 'props' of undefined
エラーメッセージの通り、propsが定義されていないよというメッセージです。
なぜこうなるのでしょうか。
ポイントはthis
です。
thisをbindさせよう
実はthisは呼ばれ方によって値が変わってきます。
要はどの時点のthisなのかによって値が変わってくる、という扱いが難しいものなのです。
そこでES5(ECMAScript 5というJavaScriptの言語仕様のバージョン)では、bind
というthis
の値を拘束してしまうメソッドが使われるようになりました。
更に、ECMAScript 2015ではより便利にしたアロー関数というものが使われるようになりました。
ちょっと一言
bindが導入される以前は、thisの値を一時的に_thisやthatに格納する、などで対応することが多くありました。。thisをthatに入れる(「これ」を「あれ」に入れる)というのは、ちょっとよくわかりづらいですね。
では、早速使い方を見ていきましょう。
MDNのアロー関数の例を見ると、このようにあります。
(param1, param2, …, paramN) => { statements }
// 引数がない場合、丸括弧を書かねばいけません:
() => { statements }
今回の場合、引数はない為にこのようになります。
onClick={() => this._onClick()}
ちょっとわかりにくいかもしれませんが、onClickイベントのときに実行される関数として、onClickを実行する際のthisをbindし、この呼び出す時点のthisを_onClickに渡しています。
なので、これで_onClickの中で this.props.speaker_type
が使えるようになります。
さて、これでGoogle HomeとAlexaどちらで実行しても正しくコマンドを発音してくれるようになりました!
最終的にはこちらのコードとなりました。
src/components/speaker_button.js
import React, { Component } from 'react';
export default class SpeakerButton extends Component {
_onClick() {
let ssu = new SpeechSynthesisUtterance();
let pre_commands = '';
switch (this.props.speaker_type) {
case 'alexa': {
pre_commands = "alexa";
break;
}
case 'google': {
pre_commands = "OK Google";
break;
}
default:
break;
}
ssu.text = `${pre_commands}、音楽かけて`
ssu.lang = 'ja-JP';
speechSynthesis.speak(ssu);
}
render() {
return (
<div className="col-sm-6 mb-2 mt-2">
<button className="card" onClick={() => this._onClick()}>
<div className="card-body">
<h4 className="card-title text-left">
<i className="fas fa-play"></i>
音楽かけて
</h4>
<p className="card-text text-left">
ランダムで音楽をかけてくれるコマンドです。
</p>
</div>
</button>
</div>
);
}
}
まとめ
今回は発音部分のロジックを作りました。
またアロー関数を使用し、thisをbindしメソッド呼び出しをできるようにもしました。
ですが、当然コマンドは音楽をかけるもの以外にもたくさんあります。
そして1個1個ロジックを作っていくのは大変です。
なので次回はコマンドをデータ化したファイルを用意し、そこから読み込みコマンドを一覧表示させる処理を作っていきます。
Reactのお仕事に関するご相談
Bageleeの運営会社、palanではReactに関するお仕事のご相談を無料で承っております。
zoomなどのオンラインミーティング、お電話、貴社への訪問、いずれも可能です。
ぜひお気軽にご相談ください。
この記事は
参考になりましたか?
0
0
関連記事

2022年5月13日
Reactでオセロゲームを作る

2021年4月9日
Slack OAuth x React で Slack ユーザー認証を作ってみた!

2021年3月1日
Reactで使えるバリデーションライブラリを紹介!

2021年2月22日
Hasura Cloud × Auth0 × React でお手軽にTodoアプリを作ってみた!

2020年12月12日
Blitz.jsとTailwind CSSでメモ帳アプリの作成【第2弾】

2020年12月8日
コンポーネントを実装するときに意識すること
簡単に自分で作れるWebAR
「palanAR」はオンラインで簡単に作れるWebAR作成ツールです。WebARとはアプリを使用せずに、Webサイト上でARを体験できる新しい技術です。
palanARへ
palanでは一緒に働く仲間を募集しています
正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。
運営メンバー

Eishi Saito 総務
SIerやスタートアップ、フリーランスを経て2016年11月にpalan(旧eishis)を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。
sasakki デザイナー
アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

やまかわたかし デザイナー
フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReactやReact Nativeをよく触っています。
Sayaka Osanai デザイナー
Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた エンジニア
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

こぼり ともろう エンジニア
サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。

ささい エンジニア
フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。

Damien
WebAR/VRの企画・開発をやっています。森に住んでいます。

ゲスト bagelee

かっきー

まりな

suzuki
miyagi

ogawa
雑食デザイナー。UI/UXデザインやコーディング、時々フロントエンドやってます。最近はARも。

いわもと
デザイナーをしています。 好きな食べ物はラーメンです。

taishi kobari
フロントエンドの開発を主に担当してます。Blitz.js好きです。

kubota shogo
サーバーサイドエンジニア。Ruby on Railsを使った開発を行いつつ月500kmほど走っています!
nishi tomoya

aihara
グラフィックデザイナーから、フロントエンドエンジニアになりました。最近はWebAR/VRの開発や、Blender、Unityを触っています。モノづくりとワンコが好きです。
nagao
SIerを経てアプリのエンジニアに。xR業界に興味があり、unityを使って開発をしたりしています。

Kainuma
サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

sugimoto
asama
ando
iwasawa ayane

oshimo
異業界からやってきたデザイナー。 palanARのUIをメインに担当してます。 これからたくさん吸収していきます!