Как вернуть несколько строк JSX в другой оператор return в React?

Одиночная линия работает нормально

render: function () {
  return (
    {[1,2,3].map(function (n) {
      return <p>{n}</p>
    }}
  );
}

не для нескольких строк

render: function () {
  return (
    {[1,2,3].map(function (n) {
      return (
        <h3>Item {n}</h3>
        <p>Description {n}</p>
      )
    }}
  );
}

Спасибо.

Ответ 1

Попробуйте вспомнить теги как вызовы функций (см. docs). Тогда первый становится:

{[1,2,3].map(function (n) {
  return React.DOM.p(...);
})}

И второй:

{[1,2,3].map(function (n) {
  return (
    React.DOM.h3(...)
    React.DOM.p(...)
  )
})}

Теперь должно быть ясно, что второй фрагмент действительно не имеет смысла (вы не можете вернуть больше одного значения в JS). Вы должны либо обернуть его в другой элемент (скорее всего, то, что вы хотите, таким образом вы также можете предоставить действительное свойство key), или вы можете использовать что-то вроде этого:

{[1,2,3].map(function (n) {
  return ([
    React.DOM.h3(...),
    React.DOM.p(...)
  ]);
})}

С сахаром JSX:

{[1,2,3].map(function (n) {
  return ([
    <h3></h3>, // note the comma
    <p></p>
  ]);
})}

Вам не нужно сгладить результирующий массив, React сделает это за вас. См. Следующий скрипт http://jsfiddle.net/mEB2V/1/. Опять же: объединение двух элементов в div/раздел, скорее всего, будет более долгосрочным.

Ответ 2

Кажется, старый ответ о возврате массива больше не применяется (возможно, с React ~ 0.9, как @dogmatic69 написал в комментарии).

Документы говорят, что вам нужно вернуть один узел:

Максимальное количество корневых узлов JSX

В настоящее время в компоненте render вы можете только вернуть один узел; если у вас есть, скажем, список divs для возврата, вы должны обернуть ваши компоненты в div, span или любой другой компонент.

Не забывайте, что JSX компилируется в обычный JS; возвращение двух функций не делает синтаксического смысла. Точно так же не ставьте более одного ребенка в тройной.

Во многих случаях вы можете просто обернуть вещи в <div> или <span>.

В моем случае я хотел вернуть несколько <tr> s. Я завернул их в <tbody> - таблице разрешено иметь несколько тел.

EDIT: с React 16.0 возвращение массива, по-видимому, разрешено снова, если каждый элемент имеет key: https://facebook.github.io/react/blog/2017/09/26/react-v16.0. HTML # новых рендеринг-возвратные типы-фрагменты и-строка

EDIT: React 16.2 позволяет вам окружать список элементов с помощью <Fragment>…</Fragment> или даже <>…</>, если вы предпочитаете это в массиве: https://blog.jmes.tech/react-fragment и-семантическое HTML/

Ответ 3

Начиная с React v16.0.0, можно возвращать несколько элементов, помещая их в Array

render() {
  return (
    {[1,2,3].map(function (n) {
      return [
        <h3>Item {n}</h3>.
        <p>Description {n}</p>
      ]
    }}
  );
}

Также из React v16.2.0 представлена новая функция под названием React Fragments которую можно использовать для обертывания нескольких элементов.

render() {
  return (
    {[1,2,3].map(function (n, index) {
      return (
        <React.Fragment key={index}>
            <h3>Item {n}</h3>
            <p>Description {n}</p>
        </React.Fragment>
      )
    }}
  );
}

Согласно документации:

Обычный шаблон в React - компонент возвращает несколько элементов. Фрагменты позволяют группировать список детей без добавления дополнительных узлов в DOM.

Фрагменты, объявленные с явным синтаксисом, могут иметь ключи. Вариант использования для этого - сопоставление коллекции с массивом фрагментов - например, для создания списка описания:

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // Without the 'key', React will fire a key warning
        <React.Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
}

ключ является единственным атрибутом, который может быть передан фрагменту. В будущем мы можем добавить поддержку дополнительных атрибутов, таких как обработчики событий.

Ответ 4

Кроме того, вы можете захотеть вернуть несколько элементов списка в некоторой вспомогательной функции внутри компонента React. Просто верните массив узлов html с атрибутом key:

import React, { Component } from 'react'

class YourComponent extends Component {
  // ...

  render() {
    return (
      <ul>
        {this.renderListItems()}
      </ul>
    )
  }      

  renderListItems() {
    return [
      <li key={1}><a href="#">Link1</a></li>,
      <li key={2}><a href="#">Link2</a></li>,
      <li key={3} className="active">Active item</li>,
    ]
  }
}

Ответ 5

Здесь вы можете использовать createFragment.

https://facebook.github.io/react/docs/create-fragment.html

import createFragment from 'react-addons-create-fragment';
...
{[1,2,3].map((n) => createFragment({
    h: <h3>...</h3>,
    p: <p>...</p>
  })
)}

(используя здесь синтаксис ES6 и JSX)

сначала нужно добавить пакет react-addons-create-fragment:

npm install --save react-addons-create-fragment

Преимущество решения Jan Olaf Krems: реакция не жалуется на недостающие key

Ответ 6

обновленный

Используйте React Fragment. Это просто. Ссылка на фрагмент документации.

render() {
  return (
    <>
    {[1,2,3].map((value) => <div>{value}</div>)}
    </>
  );
}

Старый ответ - устарел

С React> 16 вы можете использовать ответную смесь.

import { Composite } from 'react-composite';

// ...

{[1,2,3].map((n) => (
  <Composite>
    <h2>Title {n}</h2>
    <p>Description {n}</p>
  </Composite>
))};

Конечно, должен быть установлен реагирующий композит.

npm install react-composite --save