Візуалізація компонентів 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}але який нічого не друкує.

Як я можу прокрутити ці дані та повернути новий елемент інтерфейсу для кожної позиції масиву?


Я можу помилитися, але я думаю, вам потрібно використовувати stationsArrзамість функції stationsвсередині render.
Тахір Ахмед

Відповіді:


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функція повинна повертати один єдиний елемент.
Тахір Ахмед

Що було б причиною для пропонування ключового атрибута для кожного елемента станції? Я запитую, що б це змінило, якщо це зараз не потрібно?
thatgibbyguy

4
@thatgibbyguy в цьому випадку це не приносить великої переваги. У більш просунутих прикладах це дозволяє покращувати ефективність рендерингу, оскільки React може легко знати, чи був існуючий вузол переміщений в інше місце в масиві станції, тим самим уникаючи знищення та відтворення існуючого вузла dom (а також постійного встановлення вузла dom) . Це в документі для реакції: facebook.github.io/react/docs/reconciliation.html#keys
Себастьян Лорбер

Трохи не в темі, але я не впевнений, як побудувати запит, щоб запитати це. Як використовувати синтаксис ES6 у наведеному вище прикладі, як можна було б передати індекс з карти? IOW, як я можу зрозуміти, чи перебуваю я в останньому вузлі масиву? Я спробував обернути паренсом, і це, здавалося, не пішло добре.
Lane Goolsby,

@ElHombre stations.map((station,index) => { })чудово працює для мене
Себастьян Лорбер

46

У мене є відповідь, яка може бути трохи менш заплутаною для таких початківців, як я. Ви можете просто використовувати mapвсередині методу візуалізації компонентів.

render () {
   return (
       <div>
           {stations.map(station => <div key={station}> {station} </div>)} 
       </div>
   );
}

11
Для цього потрібна keyпідтримка responsejs.org/docs/lists-and-keys.html#keys
Девід Барратт,

1
Іноді це набагато корисніше. :)
Ferit

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>
  )
}

Або ви можете використовувати mapфункції і стрілки, якщо ви використовуєте ES6:

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

2
Це не буде працювати в поточній версії React, ви не можете повернути масив.
Aftab Naveed

@AftabNaveed дякую, я оновив його, рендер повинен повернути один елемент, але дійсно мати масив елементів всередині цього
Домінік

Як каже @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

Звичайно, є й інші способи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.