【ざっくり翻訳】React × Laravel 5.3のwebアプリで、API経由でFacebookの投稿を動的に取得した。

お気軽に、宜しくお願い致します。やる気、でます。

読者になる

f:id:OnomimonO:20170802191852j:plain

Facebook認証について、React Native(iOS)についての検索結果が多く、 webのreactについての文献が少なかったのでメモ。

こちらの英文のチュートリアルを参考にしました。

順序に従って、原本をそのまま和訳をしながら進めていきます。 記事内での発言は、こちらのサイトの運営者の方の言葉です。 意訳も含まれるので、拙い表現などはご容赦ください。

以下チュートリアル和訳

このチュートリアルでは、React.jsを紹介し、Reactの基本概念について説明します。 始める前に、こちらを読んで、Reactの機能、利点について学んでください。 Reactがどのように動的コンテンツに対処できるかをお見せするために、私はFacebook Graph APIとそのJavascript SDKを使って、あなたのFacebookアカウントから別のコンテンツを直接取得します。

このチュートリアルは、公式のReactチュートリアルに似ていますが、既にReactに慣れていれば、おそらくこのチュートリアルはためにならないでしょう。 今後のいくつかの記事の中でReactのもう少しレベルの高いトピックを紹介することができるといいなと思います。

HTMLの準備

React.jsを使うために、最初にいくつかの主要なReact javascriptファイルを読み込む単純なHTMLページを作成します。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>React Facebook API Tutorial</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser.js"></script>
  </head>
  <body>
    <div id="content"></div>
    <script type="text/babel">
    </script>
  </body>
</html>

scriptタグにbabelという名前のスクリプトタイプが指定されています。 Reactは、Reactコンポーネントをより分かりやすく定義できる、JSXという記法を利用しています。 詳細については、こちらを参照してください。

ご覧のとおり、Reactを使用してすべてのコンテンツのHTMLを迅速かつ構造的に生成するため、HTML部分はかなりシンプルです。 チュートリアルの残りの部分では、このようなHTMLを生成するためにscriptタグ内にコードを記述することに焦点を当てます。

React Basics

Components

コンポーネントは、Reactのパンとバターです。 データを何で、どのように表示したいのかをカプセル化し、それに従ってHTMLをレンダリングします。 Reactを使用してHello Worldを印刷するコンポーネントを作成する方法を説明しましょう。

var Page = React.createClass({
  render: function() {
    return (
      <div className="page">
        Hello World
      </div>
    );
  }
});

ReactDOM.render(
  <Page />,
  document.getElementById('content')
);

最初にReact.createClass()関数を使って\というコンポーネントを作成します。コンポーネントの核となる機能の1つは、render()関数です。 render()関数は、コンポーネントが初期化されたときに何をレンダリングするかを指示します。上記のコードでは、コンポーネント内で、 “Hello World"テキストを含む\

要素で構成されています。

\

がどのように定義されているかに注目すると、引用符がないのでこの塊は文字列ではないことに気付くでしょう。ここで定義しているのはHTML文字列ではなく、JSXの記法を使用する\
要素です。この構文は、前述のbabelスクリプトコンパイルすることによって可能になります。

ReachDOM.render同様、\インスタンスを作成して関数に渡します。これは\のrender()関数を内部的に呼び出して、その内容を指定されたコンテナに挿入します。コードを実行すると、コンテンツコンテナ内に作成された “Hello World"というテキストを持つ\

要素が表示されます。これがReactを使用して実装されたHello Worldです。

Component States and Props

上記のセクションでは、Reactを使用して静的HTML要素をレンダリングする方法を見てきました。 しかし、Reactにおいて最大の利点は、動的コンテンツをレンダリングできるということです。 そのためには、まずコンポーネントの状態を理解する必要があります。

var Post = React.createClass({
  render: function() {
    return (
      <div className="post">
        {this.props.post.message}
      </div>
    );
  },
});

var Page = React.createClass({
  getInitialState: function() {
    return {posts: []};
  },
  componentDidMount: function() {
    var posts = [
      {id: 1, message: 'Hello1'},
      {id: 2, message: 'Hello2'},
    ]
    this.setState({posts: posts});
  },
  render: function() {
    return (
      <div className="page">
        {
          this.state.posts.map(function(post) {
            return <Post key={post.id} post={post} />;
          })
        }
      </div>
    );
  }
});

ReactDOM.render(
  <Page />,
  document.getElementById('content')
);

ここでは、新しいコンポーネント\を導入しています。ポストメッセージテキストを持つ\

要素を含む単純なコンテナです。ご想像のとおり、Facebookの投稿ごとにこのコンポーネントの1つを生成し、投稿メッセージを表示します。ここで注意すべきことは、Pageのrender()関数では、新しいProp属性{this.props}を参照しています。メッセージをレンダリングするためにこの属性に値を渡す方法については後で説明します。

ここで、\コンポーネントの以前の実装に基づいて、getInitialState()とcomponentDidMount()という2つの新しい関数を導入しました。

getInitialState()関数の場合、名前が示すように、コンポーネント状態のデフォルト値を初期化する場所があります。このチュートリアルでは、既定の投稿はありませんので、初期投稿の状態変数を空の配列として設定しています。

componentDidMount()関数では、コンポーネントが最初にレンダリングされたときにこの関数が呼び出されます。これは一般的に、動的データや設定タイマーなどを取得したい場所です。次のセクションでは、この機能を変更してFacebookの投稿をAPI経由で動的に取得する方法を示します。ここではどのようにコンポーネント状態が動作するかを示す目的で、静的ポスト配列変数を作成し、setState()関数でそれを適用するだけです。

setState()関数を呼び出すと、コンポーネントがrender()関数を呼び出すようにトリガされます。 render()関数は、新しい状態変数に基づいてコンポーネントを再描画するようになりました。ご覧のとおり、状態変数ポストの各エントリの\コンポーネントを作成することによって、状態を利用してrender()関数を更新しました。これにより、\コンポーネントは各投稿の対応するHTMLを生成することができます。また、注意を払うと、私たちが生成している\コンポーネントにいくつかの属性を追加しました。これらの属性は、前に説明した{this.props}属性を介してコンポーネント自体がアクセスできます。

注意すべき重要な点は、同じレベルの動的に作成されたコンポーネントごとに一意のキーを持つことをお勧めします。状態を更新すると、Reactがキーを使用して既存のコンポーネントを更新するか新しいコンポーネントを生成するかを判断します。

Facebook API Calls

任意のFacebook API呼び出しを使用するには、まずFacebookでAppを作成する必要があります。 クイックガイドについては、こちらのサイトを参照してください。

その設定が完了したら、Facebookの関連コードを追加する準備が整いました:

var Post = React.createClass({
  render: function() {
    return (
      <div className="post">
        {this.props.post.message}
      </div>
    );
  },
});

var Page = React.createClass({
  getInitialState: function() {
    return {posts: []};
  },
  componentDidMount: function() {
    var self = this;
    FB.api('/Engineering/posts', {access_token: 'APP_ID|APP_SECRET'}, function(response) {
      self.setState({posts: response.data});
    });
  },
  render: function() {
    return (
      <div className="page">
        {
          this.state.posts.map(function(post) {
            return <Post key={post.id} post={post} />;
          })
        }
      </div>
    );
  }
});

window.fbAsyncInit = function() {
  FB.init({
    appId: 'APP_ID',
    cookie: true,
    xfbml: true,
    version: 'v2.5',
  });

  ReactDOM.render(
    <Page />,
    document.getElementById('content')
  );
};

(function(d, s, id){
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) {return;}
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/sdk.js";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

上記のコードでは、前のコードと比較して2つの変更を加えました。最初の変更は、ReactDOM.render()を呼び出す前です。Facebook SDKが初期化されていることを確認します。 Facebook Javascript SDKは、読み込まれたときにwindow.fbAsyncInit()関数をトリガーします。この関数では、以前作成したFacebook Appから取得できるappIdを使用してFBオブジェクトを初期化します。準備ができたら、ReactDOM.render()を実行して、通常どおりHTMLを生成します。

2番目の変更は、\コンポーネントのcomponentDidMount()関数を少し変更したことです。ここでは、posts変数を静的に設定するのではなく、FB.api()呼び出しを使用してFacebookエンジニアリングページから/ Engineering / postsのFacebook APIから最新の投稿を取得します。

FB.api()呼び出しの最初のパラメータは、APIエンドポイント “/ Engineering / posts"です。 「エンジニアリング」はFacebookエンジニアリングページの一意のページIDで、 「投稿」アクションはこのページに属する最新の投稿を取得したいとAPIに指示します。 別のページから投稿を取得したい場合は、ページIDをここに対応するものに置き換えます。 呼び出しの2番目のパラメータは、APIに渡すフィールドです。 通常は、access_tokenはFB.login()を呼び出した後に自動的に設定されているため、 ここではaccess_tokenを渡す必要はありません。 FB.loginの動作の詳細については、こちらのサイトを参照してください。

この方法は公開ページでのみ有効です。 プライベートページの投稿を取得したい場合は、FB.login()のアクセストークンを使用する必要があります。 FB.api()呼び出しの3番目のパラメータは、APIからの結果を渡すコールバック関数です。 コールバックから、setState()関数を使用して投稿をレンダリングするために、投稿データを\コンポーネントに適用します。

そして、これは上のコードを実行すると、Facebookエンジニアリングの最新の投稿が表示されます。 このチュートリアルに関する質問やフィードバックがある場合は、ここにコメントを残すか、私に電子メールを送ってください。読んでくれてありがとう!

所感

入門編ということで大きくつまづくことはなかったものの、今までフロントエンドエンジニアと言いながらAPIを叩いたことがなかったので、今回はとてもいい機会になりました。 実際にプロジェクトに導入したのちの記事も近日中に書きます。