2018年5月17日

プログラミング

Reactでスマートスピーカーのコマンド発音サービスを作ろう(3)【作りながら覚えるReact】

目次

  1. はじめに
  2. 発音させる
  3. Propsの値を使う
  4. まとめ

はじめに

Reactで簡単なサービスを作りながら、使い方を覚えていくシリーズの第3弾です。

Reactでスマートスピーカーのコマンド発音サービスを作ろう(2)【作りながら覚えるReact】

前回は、ReactでSmart Speaker’s Command Speaker(SSCS)のインタフェースを作り、部分的にコンポーネント化しました。
今回は実際に発音させていく部分を作ります。

発音させる

前回まで作っていたのがこちらです。
 2018-05-17 7.13.53.png (95.9 kB)
カードにコマンドはちゃんと表示されていますが、特にクリックすることもできず、また発音もしてくれません。
このカードをクリックしたらコマンドが発音される部分を作っていきましょう。
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かと思いきや、このようなエラーが表示されます。

 2018-05-17 13.09.39.png (41.5 kB)

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個ロジックを作っていくのは大変です。

なので次回はコマンドをデータ化したファイルを用意し、そこから読み込みコマンドを一覧表示させる処理を作っていきます。

0

0

AUTHOR

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にeishis, Inc.を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

palanでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にeishis, Inc.を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

しまだ

しまだ デザイナー

WebAR/VRのデザインと3DCG制作がメインです。 肩書きは「アニメ案件に関わりたいデザイナー」。

Miu マーケター

ドイツでWEBマーケティングしています。

しんのき エンジニア

主に React Native を使ったアプリ開発と AWS や Firebase を使ったサーバーレスアーキテクチャを担当しています。元々はインフラとかPHPをやっていました。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReact NativeやReact360をよく触っています。

furuya エンジニア

サーバーサイド、フロントエンド、Unityと色々手を出してる雑食系エンジニア。ReactNativeが最近のマイブーム。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

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

うえまつゆい エンジニア

サーバーサイドエンジニアからフロントエンドエンジニアになりました。主にReact Nativeでのアプリ開発をしています。

kobori

こぼり ともろう エンジニア

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

sasai

ささい エンジニア

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

damien

Damien

WebAR/VRを中心に企画やディレクションやエンジニアもちょっとやっています。森に住んでいます。

デザイナーゲスト

ゲスト デザイナー

CONTACT PAGE TOP