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

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

React使ってSPAを作るよ目次

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

ReactでJSONファイルからデータを持ってくる

これまでJSXの中で直接JSONデータを記述していましたが、これを外部ファイルにして読み込むようにしたいと思います。

JSONファイルからデータを持ってくる部分は、この記事を参考にしました。

記事コンポーネントリストの中身をこのように書き換えます。
jQuery入れといてよかった。

//記事リストコンポーネント
var ArticleArea = React.createClass({

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

  render: function() {
    var articleNodes = this.state.data.map(function(article) {
      return (
        <ArticleList articleTag={article.tagData} articleMark={article.markData} articleComment={article.commentData} articleTitle={article.articleTitle} articleUrl={article.articleUrl} articleDescription={article.articleDescription} articleImage={article.articleImage} />
      )
    });
    return (
    <ul id="article-list">
      {articleNodes}
    </ul>
    )
  }
});

JSONデータ取得部分が丸々追加されています。
気をつける点は、JSONファイルの読み込み時にstateに初期値を入れてるので、map関数のところを「this.props.data.map」から「this.state.data.map」に変えておくことです。

var articleNodes = this.state.data.map(function(article) {

また、これまで冒頭で設定していたarticleDataを渡す必要がなくなったので、data={articleData}は削除します。

/* React + JSX */
React.render(
  <ArticleArea />,
  document.getElementById('container')
);

Chromeでめっちゃエラー出るわ

JSONファイルのパスを指定して、そこからデータを持ってきたいわけですが、ローカルで作業していてChromeで確認するとエラーが出ます( ゚ε゚;)ムムッ

「XMLHttpRequest cannot load」とか。
「Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.」とか言われます。

これは何かというと、ローカルファイルを参照しようとしたときに出るもので、こちらの記事に詳しい説明があります。

というわけで、とりあえずブラウザチェックはFirefoxで行うことにします(;´Д`)

JSONファイルを作る

そして肝心のJSONファイルですが、もともとjsx側で書いていたデータをそのままJSONファイルに持っていくと、たとえFirefoxで確認してもエラーが出ます。

「SyntaxError: JSON.parse: expected property name or ‘}’ at line 3 column 5 of the JSON data」みたいなことを言われます。

「ここにはプロパティ名か } が入るはずだと思うんですけどー?」って言われています。
簡単な話で、JSONはkey:valueを両方とも文字列または数値で記述する必要があり、

    articleTitle: "記事その1タイトル",
    articleUrl: "記事その1URL",
    articleDescription: "記事その1description",
    articleImage: "https://source.unsplash.com/random",

こういう書き方だとダメ。
だからプロパティ名が認識できていない、ってことですね。
文字列であれば「”」で囲って、

    "articleTitle": "記事その1タイトル",
    "articleUrl": "記事その1URL",
    "articleDescription": "記事その1description",
    "articleImage": "https://source.unsplash.com/random",

こんなふうにしないといけないわけですね。

ところがJSX側だとプロパティ名を「”」で囲むとエラーになっちゃうんですよね。
この仕組みがいまだによくわかりません。
ふしぎ・・・

ちなみにJSONファイルの全文はこうなりました。

[
  {
    "articleTitle": "記事その1タイトル",
    "articleUrl": "記事その1URL",
    "articleDescription": "記事その1description",
    "articleImage": "https://source.unsplash.com/random",
    "tagData": [
      {
      "tag": "タグ1",
      "tagUrl": ""
      },
      {
      "tag": "タグ2",
      "tagUrl": ""
      },
      {
      "tag": "タグ3",
      "tagUrl": ""
      }            
    ],
    "markData": [
      {
       "account": "ユーザー1-1",
       "accountImage": "https://source.unsplash.com/random"
      },
      {
       "account": "ユーザー1-2",
       "accountImage": "https://source.unsplash.com/random"
      },
      {
       "account": "ユーザー1-3",
       "accountImage": "https://source.unsplash.com/random"
      }
    ],
    "commentData": [
      {
       "author": "その1ユーザー1",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その1コメント1"
      },
      {
       "author": "その1ユーザー2",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その1コメント2"
      },
      {
       "author": "その1ユーザー3",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その1コメント3"
      }
    ]
  },
  {
    "articleTitle": "記事その2タイトル",
    "articleUrl": "記事その2URL",
    "articleDescription": "記事その2description",
    "articleImage": "https://source.unsplash.com/random",
    "tagData": [
      {
      "tag": "タグ1",
      "tagUrl": ""
      },
      {
      "tag": "タグ2",
      "tagUrl": ""
      },
      {
      "tag": "タグ3",
      "tagUrl": ""
      }            
    ],
    "markData": [
      {
       "account": "ユーザー2-1",
       "accountImage": "https://source.unsplash.com/random"
      },
      {
       "account": "ユーザー2-2",
       "accountImage": "https://source.unsplash.com/random"
      },
      {
       "account": "ユーザー2-3",
       "accountImage": "https://source.unsplash.com/random"
      }
    ],
    "commentData": [
      {
       "author": "その2ユーザー1",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その2コメント1"
      },
      {
       "author": "その2ユーザー2",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その2コメント2"
      },
      {
       "author": "その2ユーザー3",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その2コメント3"
      }
    ]
  },
  {
    "articleTitle": "記事その3タイトル",
    "articleUrl": "記事その3URL",
    "articleDescription": "記事その3description",
    "articleImage": "https://source.unsplash.com/random",
    "tagData": [
      {
      "tag": "タグ1",
      "tagUrl": ""
      },
      {
      "tag": "タグ2",
      "tagUrl": ""
      },
      {
      "tag": "タグ3",
      "tagUrl": ""
      }            
    ],
    "markData": [
      {
       "account": "ユーザー3-1",
       "accountImage": "https://source.unsplash.com/random"
      },
      {
       "account": "ユーザー3-2",
       "accountImage": "https://source.unsplash.com/random"
      },
      {
       "account": "ユーザー3-3",
       "accountImage": "https://source.unsplash.com/random"
      }
    ],
    "commentData": [
      {
       "author": "その3ユーザー1",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その3コメント1"
      },
      {
       "author": "その3ユーザー2",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その3コメント2"
      },
      {
       "author": "その3ユーザー3",
       "authorImage": "https://source.unsplash.com/random",
       "comment": "その3コメント3"
      }
    ]
  }
]

で、これをFirefoxで確認すると、エラーは出ないのですが警告が出てきました。

「Warning: Each child in an array or iterator should have a unique “key” prop. Check the render method of ArticleArea. See https://fb.me/react-warning-keys for more information.」

ArticleArea、TagList、MarkList、CommentListの4件について、固有のkeyを持たせるべきですよ、と。
それはなんなの?持たせないとどうなるの?というのはこちらの記事が詳しいです。

・・・ということですが私にはまだよくわかりません(;´Д`)

ひとまずこのまま進めていって、問題が出てきたら対応してみようと思います。
記事ごとのIDか何か持たせておかないとコメントの追加をするときなどに困りそうな気もするので、いずれはそういった処理も入れることになるでしょうね・・・
…ゴクリ…(`・д´・ ;)

React使ってSPAを作るよ目次