54
50

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.

React+Youtube APIでデータを取得して動画を埋め込む

Posted at

概要

YouTube Data API(v3)で検索からYoutubeデータ取得し、iframeで動画を埋め込みたい。

公式リファレンス
YouTube Data API(v3)
IFrame Player API

前提

・node.jsとnpm
・Youtube APIのアクセスkey

Youtube Data API Key の取得手順

準備

create-react-appで始めていきます。

$ create-react-app project
$ cd project
$ npm start

public/srcにcomponentsディレクトリを追加して、下記の構成にする(各ディレクトリ以下はindex.js)

components
  ├── Header
  └── Youtube

Youtube APIからデータ取得

初めにAPIからデータをaxiosを使って取得します。

axiosのインストール

$ npm install axios --save

App.jsを編集して、とりあえず以下の条件で取得できるか試してみます。
・ 検索ワード: Create-React-APP
・ 検索数は: 3

期待する検索結果のJSON構造はこの形式


{
  "kind": "youtube#searchResult",
  "etag": etag,
  "id": {
    "kind": string,
    "videoId": string,
    "channelId": string,
    "playlistId": string
  },
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string
  }
}

App.js編集

src/App.js

import React from 'react';
import axios from 'axios';

const YOUTUBE_API_KEY = process.env.REACT_APP_YOUTUBE_API_KEY;

export default class App extends React.Component {
  state = {
    videos: [],
    keyword: 'Create-React-APP'
  }

  componentDidMount() {
    const url = `https://www.googleapis.com/youtube/v3/search?type=video&part=snippet&q=${this.state.keyword}&maxResults=3&key=${YOUTUBE_API_KEY}`;

    axios
      .get(url)
      .then(response => {
          this.setState({
            videos: response.data.items,
          });
      })
      .catch(() => {
          console.log('通信に失敗しました');
      });
  }

  render() {
    console.log(this.state.videos)
    return (
      <>
      </>
    )
  }
}

create-react-appでは、gitignoreにデフォルトでenv.localが入っているので.env.localを作成してここにアクセスキーを記述する。

REACT_APPを前につける必要があり、JS側では記述したKeyの名前の先頭にprocess.envをつけることで取得できる

.env.local
# API
REACT_APP_YOUTUBE_API_KEY = '自分のアクセスキー'

反映する為に立ち上げ直す

$ npm start

コンソールを確認するとこのようになり
スクリーンショット 2019-07-20 18.17.34.png

条件通り取得できています

検索フォームの作成

では、検索フォームで入力したキーワードから取得できるようにしていきます。

再度App.jsの修正します。
APIのパラメータに検索フォームの値を使いたいのでのonSerchYoutube関数を記述し、値を受け取る為Header/index.jsにpropsとして渡します。

src/App.js
import React from 'react';
import axios from 'axios';
import Header from './components/Header';

const YOUTUBE_API_KEY = process.env.REACT_APP_YOUTUBE_API_KEY;

export default class App extends React.Component {
  state = {
    videos: [],
  }

  onSerchYoutube = (keyword) => {
    const url = `https://www.googleapis.com/youtube/v3/search?type=video&part=snippet&q=${keyword}&maxResults=3&key=${YOUTUBE_API_KEY}`;

    axios
      .get(url)
      .then(response => {
          this.setState({
            videos: response.data.items,
          });
      })
      .catch(() => {
          console.log('通信に失敗しました');
      });
  }

  render() {
    return (
      <>
        <Header onSerchYoutube={this.onSerchYoutube} />
      </>
    )
  }
}

Header/index.jsに検索フォームを置いていきます。

YouTube APIではクォータの使用量が決まっており、使用量を考えなければ、一日の上限を超え制限がかかる恐れが有ります。

検索フォームでは、onChangeする度にAPIを呼び出されてしまうので、lodashのdebounceを活用し制限します。

lodashインストール

$ npm install --save lodash

debounceは更新中は関数を呼び出さずに、任意の時間内で更新されなかった時、関数を実行するようにできます。今回は0.2秒の待ち時間を与えます。

参考: https://qiita.com/waterada/items/986660d31bc107dbd91c

Header/index.js
import React from 'react';
import _ from 'lodash';

export default class Header extends React.Component {

    state = {
        keyword: "",
    };
    
    handleChangeInput = (e) => {
        this.setState({keyword: e.target.value});
        this._debounce(e.target.value)
    }

    _debounce = _.debounce(value => {
        this.props.onSerchYoutube(value);
    },200);

    render() {
        return (
            <div style={{marginTop: '20px', textAlign:'center'}}>
                <input 
                  onChange={this.handleChangeInput}
                  value={this.state.keyword}
                />
            </div>
        )
    }
}

これで検索ワードからYoutubeのデータが取得できました。

YouTubeを埋め込む

データからYouTubeを埋め込んでいきます。

Youtube/index.jsにstateのvideos渡すようにApp.jsを編集。

App.js
// 追加
import Youtube from './components/Youtube';
...

render() {
    return (
      <>
        <Header onSerchYoutube={this.onSerchYoutube} />
        {/* 追加 */}
        <Youtube videos={this.state.videos}/>
      </>
    )
  }

APIリファレンスIFrame Player APIから

<iframe id="ytplayer" type="text/html" width="640" height="360"
  src="http://www.youtube.com/embed/M7lc1UVf-VE?autoplay=1&origin=http://example.com"
  frameborder="0"/>

iframeタグのurlにpropsをmapした各videoのvideoIdを入れる。

Youtube/index.jsの作成

Youtube/index.js
import React from 'react';

const Youtube = (props) => {

    const video = props.videos.map((video) => {
        const url = 'https://www.youtube.com/embed/' + video.id.videoId;

        return ( 
            <div style={{margin: '20px', textAlign: 'center'}}>
                <iframe 
                  id="ytplayer" 
                  type="ytplayer" 
                  width="480" 
                  height="270"
                  src={url}
                  frameborder="0"
                />
            </div>
        )
    });

    return (
        <div style={{marginTop: '10px'}}>
          {video}
        </div>
    )
    
}

export default Youtube;

最終的な動き

ezgif.com-video-to-gif.gif

これでReactでYoutubeデータの取得から埋め込みまで出来ました。

以上です。

54
50
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
54
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?