Reactの別のreturnステートメントで複数行JSXを返す方法は?


100

単一行は正常に動作します

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
:この特定の問題に関する詳細情報についてはgithub.com/facebook/react/issues/2127
plus-

return ("asdf" "asdf");たくないreturn ["asdf", "asdf"];
neaumusic

回答:


149

タグを関数呼び出しと考えてみてください(docsを参照)。次に、最初のものは次のようになります。

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

そして2番目のもの:

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

これで、2番目のスニペットが実際には意味をなさないことが明らかになります(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/を参照してください。繰り返しますが、2つの要素をdiv / sectionにラップする方が長期的には良いでしょう。


4
うん、実際に明確に文書facebook.github.io/react/tips/...
ショーン

1
フラット化ビットなしでreturn([...])を使用すると、希望どおりのマークアップが得られますが、返された配列はフラットトレンドである必要はありませんが、特定のケースでは、最終的な出力には影響しません。またはそれは?
Shawn

ありがとう!ティル!回答を更新して、flattenがオプションであることを示すJSFiddleへのリンクを含めます。Reactドキュメントへのリンクも含まれます。
Jan Olaf Krems、2014年

13
(0.9ishのように)このもはや作品Uncaught Error: Invariant Violation: Product.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
dogmatic69

2
@TimFletcher コンポーネントレンダリングの一部として配列を返すことは問題ありません<div>{ this.props.foos.map(function() { return <Foo /> }) }</div>。ただし、renderコンポーネントの関数は、たとえばdiv内でラップせずにその配列を返すことはできません。
Henrik N

35

配列を返すことについての古い答えはもはや適用されないようです(おそらくReact〜0.9以降、@ dogmatic69がコメントに書いたように)。

ドキュメントは単一のノードを返す必要があると言います:

JSXルートノードの最大数

現在、コンポーネントのレンダーでは、1つのノードのみを返すことができます。たとえば、返すdivのリストがある場合は、div、span、またはその他のコンポーネント内でコンポーネントをラップする必要があります。

JSXが通常のJSにコンパイルされることを忘れないでください。2つの関数を返すことは、実際には構文的に意味がありません。同様に、1つに3人以上の子供を入れないでください。

多くの場合、単純にa <div>またはa<span>

私の場合、複数<tr>のを返したかった。私はそれらを<tbody> –テーブルは複数のボディを持つことができます。

編集:React 16.0以降、各要素に次のものが含まれている限り、配列を返すことが再び許可されているようkeyです:https//facebook.github.io/react/blog/2017/09/26/react-v16.0.html #new-render-return-types-fragments-and-strings

編集:React 16.2では、配列より<Fragment>…</Fragment>も要素のリスト<>…</>を好む場合は、またはで要素のリストを囲むことができます:https : //blog.jmes.tech/react-fragment-and-semantic-html/


3
複数返却したい場合はどうすればよいです<li>か?私はそれをすべてラップすることができないと仮定して<ul>
Banjocat '10

@Banjocatわからない:/ リストをネストすることが許可されているので<li><ul><li>one</li><li>two</li></ul></li>、状況に応じて動作するようなものを返すことができます。または:ラッピングdivは厳密には有効ではありませんが、関連するすべてのブラウザーで正常にレンダリングされますか?ぜひお試しください。
Henrik N

1
@Banjocat ...私はあなたの質問に対するより良い答えを知りたいです。たぶん、あなたはそれを通常のスタックオーバーフローの質問のように見せて、別の答えを得るかどうかを確認する必要があります。
user1175849 2015年

@ user1175849たぶん、その質問を投稿できます :)
Henrik N

1
@HenrikN FWIWは、の「サブセット」をラップlispanまたはdiv私のためにうまく動作しませんでした。divはレンダリングに深刻な影響を及ぼし、少なくとも私の使用例では、スパンがCSSを混乱させていました。2¢:li sのいくつかのサブセットを返そうとすると、コードのにおいがします。私たちはul一種のプルダウンメニューとしてa を使用していましたが、最初は多くのコンポーネントがの「セクション」を返すことを望んでいましたli。結局のところ、すべてのメニューコードを単一のコンポーネントに「アンカー」して、複数のソースからのulshorn を使用するよりも優れていましたli。UIのメンタルモデルも少しクリーンになったと思います。
ルフィン

13

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

keyは、Fragmentに渡すことができる唯一の属性です。将来的には、イベントハンドラーなどの追加属性のサポートを追加する可能性があります。


7

また、Reactコンポーネント内のヘルパー関数でいくつかのリスト項目を返すこともできます。次のkey属性を持つhtmlノードの配列を返すだけです。

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>,
    ]
  }
}

2

使用できます 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


私が間違っている場合は私を修正しますが、手動でキーを追加できます。1月の例を使用:最初の配列項目は、例えば、<h3 key = {i}> </ h3>を取得し、2番目の配列項目は、<p> key = {i + '-foo'}> </ p>のようにわずかに異なります
nerdess

2

更新しました

React Fragmentを使用します。それは簡単です。フラグメントのドキュメントへのリンク

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

古い答え-廃止

React> 16では、react-compositeを使用できます。

import { Composite } from 'react-composite';

// ...

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

もちろん、react-compositeをインストールする必要があります。

npm install react-composite --save

0

Reactフラグメント<></>React.Fragment

return (
    <>
      {[1, 2, 3].map(
        (n, index): ReactElement => (
          <React.Fragment key={index}>
            <h3>Item {n}</h3>
            <p>Description {n}</p>
          </React.Fragment>
        ),
      )}
    </>
  );
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.