オブジェクトの配列からのReactコンポーネントのレンダリング


98

オブジェクトを含む配列であるステーションと呼ばれるデータがあります。

stations : [
  {call:'station one',frequency:'000'},
  {call:'station two',frequency:'001'}
]

各配列位置のUIコンポーネントをレンダリングしたいのですが。これまでのところ私は書くことができます

 var stationsArr = []
 for (var i = 0; i < this.data.stations.length; i++) {
     stationsArr.push(
         <div className="station">
             {this.data}
         </div>
     )
 }

そしてレンダリングします

render(){
 return (
   {stationsArr}
 )
}

問題は、すべてのデータが印刷されることです。代わりに、次のようなキーを表示したいのです{this.data.call}が、何も出力されません。

このデータをループして、配列の各位置の新しいUI要素を返すにはどうすればよいですか?


私は間違っている可能性がありますが、関数内ではstationsArrなく使用する必要があると思います。stationsrender
Tahir Ahmed

回答:


151

ステーションのリストをReactElementsにマップできます。

React> = 16では、追加のhtml要素ラッパーを必要とせずに、同じコンポーネントから複数の要素を返すことが可能です。16.2以降、フラグメントを作成するための新しい構文<>があります。これが機能しない場合、またはIDEでサポートされていない場合は、<React.Fragment>代わりに使用できます。16.0から16.2の間では、フラグメントに非常に単純なポリフィルを使用できます。

以下をお試しください

// Modern syntax >= React 16.2.0
const Test = ({stations}) => (
  <>
    {stations.map(station => (
      <div className="station" key={station.call}>{station.call}</div>
    ))}
  </>
); 

// Modern syntax < React 16.2.0
// You need to wrap in an extra element like div here

const Test = ({stations}) => (
  <div>
    {stations.map(station => (
      <div className="station" key={station.call}>{station.call}</div>
    ))}
  </div>
); 

// old syntax
var Test = React.createClass({
    render: function() {
        var stationComponents = this.props.stations.map(function(station) {
            return <div className="station" key={station.call}>{station.call}</div>;
        });
        return <div>{stationComponents}</div>;
    }
});

var stations = [
  {call:'station one',frequency:'000'},
  {call:'station two',frequency:'001'}
]; 

ReactDOM.render(
  <div>
    <Test stations={stations} />
  </div>,
  document.getElementById('container')
);

key属性を忘れないでください!

https://jsfiddle.net/69z2wepo/14377/


@thatgibbyguy:そうそう!それが正解かもしれません。子コンポーネントをラップする必要があります。あなたのrender関数は、1つの要素を返す必要があります。
Tahir Ahmed

各測点要素のキー属性を提案する理由は何ですか?私が求めているのは、今それが必要なくなった場合、何が変わるでしょうか?
thatgibbyguy

4
この場合の@thatgibbyguyは、あまりメリットがありません。より高度な例では、既存のノードがステーションアレイ内の別の場所に移動されたかどうかをReactが簡単に認識できるため、より優れたレンダリングパフォーマンスが可能になり、既存のdomノードの破壊と再作成を回避します(domノードをマウントしたままにすることもできます)。 。それは反応ドキュメントにあります:facebook.github.io/react/docs/reconciliation.html#keys
Sebastien Lorber

トピックから少し外れていますが、これを尋ねるクエリを作成する方法はわかりません。上記の例でES6構文を使用する場合、マップからインデックスを渡すにはどうすればよいでしょうか?IOW、配列の最後のノードにいるかどうかはどうすればわかりますか?かっこで包んでみましたがうまくいきませんでした。
Lane Goolsby、2017

@ElHombre stations.map((station,index) => { })はうまく機能します
Sebastien Lorber


6

this.data おそらくすべてのデータが含まれているため、次のようにする必要があります。

var stations = [];
var stationData = this.data.stations;

for (var i = 0; i < stationData.length; i++) {
    stations.push(
        <div key={stationData[i].call} className="station">
            Call: {stationData[i].call}, Freq: {stationData[i].frequency}
        </div>
    )
}

render() {
  return (
    <div className="stations">{stations}</div>
  )
}

または、mapES6を使用している場合は、矢印関数を使用できます。

const stations = this.data.stations.map(station =>
    <div key={station.call} className="station">
      Call: {station.call}, Freq: {station.frequency}
    </div>
);

2
これは現在のReactバージョンでは機能せず、配列を返すことはできません。
Aftab Naveed 2017年

@AftabNaveedおかげで更新しました。renderは1つの要素を返す必要がありますが、その中に要素の配列があることは有効です
Dominic

@AftabNaveedが言うように、反応バージョンが16未満の場合は、上記を使用する必要があります。それ以外の場合は、return stations;codepen.io/pawelgrzybek/pen/WZEKWj
チキンスープ

1

使用できる方法はいくつかあります。

const stations = [
  {call:'station one',frequency:'000'},
  {call:'station two',frequency:'001'}
];
const callList = stations.map(({call}) => call)

解決策1

<p>{callList.join(', ')}</p>

解決策2

<ol>    
  { callList && callList.map(item => <li>{item}</li>) }
</ol>

kind-antonelli-z8372を編集

もちろん、他にも利用可能な方法があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.