React使ってSPAを作るよ(7)

React使ってSPAを作るよ(7)

React使ってSPAを作るよ目次

React使ってSPAを作るよ(6)の続きです。

これまでJSONファイルからデータを読み込んできましたが、これを、URLからOGPデータを取得しにいくように変えたいと思います。

OGPデータを取得してReactで描画する

まずは適当なURLのリスト、/data/list.jsonというファイルを用意。

{
	"Result":0,
	"article_list":
	[
		{
			"url":"http://example.com"
		},
		{
			"url":"https://example.com"
		},
		{
			"url":"http://example.com"
		},
		{
			"url":"http://example.com"
		},
		{
			"url":"http://example.com"
		}
	]
}

そしてPHPはこんな感じ。
同僚がドラフト版として簡単なPHPファイルを用意してくれました。
opengraph-masterというライブラリを使っているようですね。

 <?php
/*
  OGPの情報を取得する
  取得対象URLの一覧はlist.jsonで管理
*/

define('DATA_PATH',    '../data/');	// データディレクトリ
require_once('./lib/opengraph-master/OpenGraph.php');

class getOgpList {

	public static function main() {

		$res = array();

		// 一覧に表示する記事の情報を取得する
		$list_json    = file_get_contents(DATA_PATH . 'list.json', false);
		$article_list = json_decode($list_json, true)['article_list'];
		foreach ($article_list as $key => $val) {
			$article_data = array();
			
			$graph = OpenGraph::fetch($val['url']);
			$article_data['articleTitle']       = $graph->title;
			$article_data['articleUrl']         = $val['url'];
			$article_data['articleDescription'] = $graph->title;
			$article_data['articleImage']       = $graph->image;
			
			$res[] = $article_data;
		}

    header( 'Content-Type: text/javascript; charset=utf-8' );
    echo $_GET['callback'] . "(" . json_encode($res). ")";
		return;
	}
}

$obj = new getOgpList();
$obj->main();

?>

JSONのファイル名は自由に変えて大丈夫です。

最後のほうにある2行

    header( 'Content-Type: text/javascript; charset=utf-8' );
    echo $_GET['callback'] . "(" . json_encode($res). ")";

ここだけ私のほうで書き換えました。
あちこちのサイトを参考にしてこの形に落ち着きました・・・

サンプルのPHPでは記事リンク部分のデータしかないので、とりあえずタグやコメントは無視して作りましょう。
ArticleListコンポーネントはそのまま変更なしでOK。
続いて、ArticleAreaコンポーネントでJSONを読み込みます。

  //JSONデータ取得
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    $.ajax({
      url: 'PHPファイルのパス',
      dataType: 'jsonp',
      cache: false,
      jsonpCallback: 'callback',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error('PHPファイルのパス', status, err.toString());
      }.bind(this)
    });
  },

今までarticle.jsonを読み込んでいましたが、PHPに変えたのでurlを修正します。
さらに、dataTypeにjsonpを指定。
jsonpCallbackで、PHP側のコールバックを指定します。

ところでこのsuccess/errorっていうのを、できればチェインメソッドで.doneとかしたいですね。でも下手なことして動かなくなっても困るのでとりあえず今は直さずにそのままにしておきますね(;´Д`)

なぜコールバックを使うのか、jsonpとはなんぞや?というのはこの記事が詳しくてわかりやすいです。

eval関数はあんまりよくないらしいっていう記事も見たのですが詳しくはわかりません・・・

OGPを取得するということは、異なるドメインの他サイトのデータを取ってこないといけないわけですね。
ローカルのJSONファイルを使うときも、Chromeではアクセスできないようになっていましたし、セキュリティの問題があるわけですね~。

クリックイベントがきかなくなった

これをブラウザで表示してみると、実際にlist.jsonに設定したURLの記事タイトルや画像などを表示することができました!

しかし・・・
記事をクリックしても、オーバーレイが表示されません!
ガ━━(;゚Д゚)━━ン!!

$.ajaxがいけないのか?と思いましたが、article.jsonから読み込んでいたときは、記事がクリックできてオーバーレイ表示もされていました。

じゃあ、PHPがいけないのか?と思いましたが、エラーがあるならそもそもOGPデータもとれないはず。

じゃあ、JSXがいけないのか?と思いましたが、エラーがあるならそもそもリストが表示されないはず。

じゃあ、HTML/CSSがいけないのか?と思いましたが、出力されたHTMLソースをindex.htmlに直接入れておくとそれはクリックできるしオーバーレイも表示されます。

ということは・・・?

答えは過去の記事、jsで追加した要素のclickイベントが発火しない!にありました。

  $('article').on(eTouchStart, function(e){

となっていたところを、

  $('body').on(eTouchStart, 'article', function(e){

こうすればOK。

しかし、PHPを使わずにJSONから読み込んだデータをレンダリングしていたときは大丈夫だったのに、PHPを通す方法にしたらこうなるんですね?DOM追加の仕組みや、もしくはタイミングなどが異なるのでしょうか・・・???ajaxでデータを取ってくるのに時間がかかるからとか・・・?

(´ε`;)ウーン…

React使ってSPAを作るよ目次