loading...
gumi TECH Blog

React入門 03: JSON形式の配列から複数データを取り出してページに表示する

gumitech profile image gumi TECH ・2 min read

ページに表示するデータは、サーバーなどから得ることが多いでしょう。その場合、JSON形式が扱いやすく、APIから返すデータなどにもよく使われています。今回は、データのやり取りは置いておき、変数に納めた配列から取り出したデータを、コンポーネントのテキストとして表示してみます。手を加えるのは、「React入門 02: ライブラリMarkedでMarkdownの機能を加える」で書いたアプリケーションのモジュールです。

配列にまとめたJSONデータを子コンポーネントに渡す

データのテキストはJSONのかたちにして、大もとのコンポーネント(src/App.js)のクラス(App)のプロパティ(data)として、つぎのように配列要素として納めます。その値は、テンプレートの子コンポーネント(CommentList)のタグに同名の属性(data)として与えましょう。これで、子コンポーネントはプロパティから値が参照できます。

function App() {
  const data = [
    {author: "ヘンリー・キッシンジャー", text: "チャンスは__貯金__できない。"},
    {author: "マーク・トウェイン", text: "禁煙なんてたやすい。私は*何千回*もやった。"}
  ];
  return (
    <div className="App">
      <h1>コメント</h1>
      {/* <CommentList /> */}
      <CommentList data={data} />

    </div>
  );
}

複数データからテンプレートをつくる

子コンポーネント(src/components/CommentList.js)が親から引数オブジェクトに受け取るプロパティ(data)は配列です。配列要素すべてをコンポーネントに表示するには、その数だけテンプレートが必要になります。

そこで、関数コンポーネントの中で、以下に抜き書きしたコードのようにArray.prototype.map()メソッドでJSXテンプレートから要素をつくって変数(commentNodes)に配列で納めます。これを波かっこ{}に入れてテンプレートに加えれば、配列の要素すべてが差し込まれる仕組みです(「複数のコンポーネントをレンダリングする」)1。これで、配列要素のデータが取り出されてページに表示できます(図001)。

なお、要素には一意の値をkey属性として与えなければなりません。Reactが要素の変更をkeyにもとづいて識別するためです。

// const CommentList = () => {
const CommentList = (props) => {
  const commentNodes = props.data.map((comment, id) => (
    <Comment author={comment.author} key={id}>
    {comment.text}
    </Comment>
  ));
  return (
    <div className="CommentList">
      {/* <Comment author="ヘンリー・キッシンジャー">
      チャンスは__貯金__できない。
      </Comment>
      <Comment author="マーク・トウェイン">
      禁煙なんてたやすい。私は*何千回*もやった。
      </Comment> */}
      {commentNodes}
    </div>
  );
};

図001■配列のJSONデータが取り出されて子コンポーネントに表示される

02_004.png

書き改めたコンポーネントふたつのJavaScriptコード全体は、つぎのとおりです(コード001および002)。

コード001■src/components/CommentList.js

import React from 'react';
import Comment from './Comment';

const CommentList = (props) => {
  const commentNodes = props.data.map((comment, id) => (
    <Comment author={comment.author} key={id}>
    {comment.text}
    </Comment>
  ));
  return (
    <div className="CommentList">
      {commentNodes}
    </div>
  );
};

export default CommentList;

コード002■src/App.js

import React from 'react';
import CommentList from './components/CommentList';
import CommentForm from './components/CommentForm';
import './App.css';

function App() {
  const data = [
    {author: "ヘンリー・キッシンジャー", text: "チャンスは__貯金__できない。"},
    {author: "マーク・トウェイン", text: "禁煙なんてたやすい。私は*何千回*もやった。"}
  ];
  return (
    <div className="App">
      <h1>コメント</h1>
      <CommentList data={data} />
      <CommentForm />
    </div>
  );
}

export default App;

  1. Vue.jsではテンプレートに特別な属性(ディレクティブ)v-forを加えることで、データの数だけテンプレートがつくられて差し込まれます(「Vue.js入門 03: データから動的にリストをつくる」01「項目のデータを複数にする」参照)。つまり、JavaScriptコードでテンプレートをつくる必要はありません。

    Angularも、ほぼ同じ構文のディレクティブ*ngForを備えています(「Display a Heroes List」「List heroes with *ngFor」参照)。 

Discussion

pic
Editor guide