Làm cách nào để trả về nhiều dòng JSX trong một câu lệnh trả về khác trong React?


100

Một dòng hoạt động tốt

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

không cho nhiều dòng

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

Cảm ơn.


1
Để biết thêm thông tin về vấn đề cụ thể này: github.com/facebook/react/issues/2127
plus-

không return ("asdf" "asdf");bạn muốnreturn ["asdf", "asdf"];
neaumusic

Câu trả lời:


149

Hãy thử nghĩ về các thẻ như là lời gọi hàm (xem tài liệu ). Sau đó, cái đầu tiên trở thành:

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

Và cái thứ hai:

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

Bây giờ phải rõ ràng rằng đoạn mã thứ hai không thực sự có ý nghĩa (bạn không thể trả về nhiều hơn một giá trị trong JS). Bạn phải bọc nó trong một phần tử khác (rất có thể là thứ bạn muốn, theo cách đó, bạn cũng có thể cung cấp một thuộc tính hợp lệ key) hoặc bạn có thể sử dụng một cái gì đó như sau:

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

Với đường JSX:

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

Bạn không cần phải làm phẳng mảng kết quả, React sẽ làm điều đó cho bạn. Xem fiddle http://jsfiddle.net/mEB2V/1/ sau đây . Một lần nữa: Gói hai phần tử thành một div / section rất có thể sẽ tốt hơn về lâu dài.


4
Yep thực sự đã ghi lại rõ ràng facebook.github.io/react/tips/…
Shawn

1
Sử dụng return ([...]) mà không có bit làm phẳng mang lại cho tôi đánh dấu chính xác như tôi muốn, mặc dù mảng được trả về không được làm phẳng nhưng trong trường hợp cụ thể của tôi, nó không ảnh hưởng đến kết quả cuối cùng. Hoặc là nó?
Shawn

Cảm ơn! TIL! Cập nhật câu trả lời của tôi để bao gồm một liên kết đến JSFiddle cho thấy rằng làm phẳng là tùy chọn. Cũng sẽ bao gồm liên kết đến tài liệu React.
Jan Olaf Krems

13
Này không còn hoạt động (tính đến 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 Đó là tốt để trả lại một mảng như một phần của render một thành phần, ví dụ <div>{ this.props.foos.map(function() { return <Foo /> }) }</div>. Nhưng renderhàm của thành phần không thể trả về mảng đó mà không bao bọc nó, ví dụ như trong một div.
Henrik N

35

Có vẻ như câu trả lời cũ về việc trả về một mảng không còn được áp dụng nữa (có thể kể từ React ~ 0.9, như @ dogmatic69 đã viết trong một nhận xét ).

Tài liệu nói rằng bạn cần trả về một nút duy nhất:

Số lượng mã gốc JSX tối đa

Hiện tại, trong kết xuất của một thành phần, bạn chỉ có thể trả về một nút; Ví dụ, nếu bạn có một danh sách các div để trả về, bạn phải bao bọc các thành phần của mình trong một div, span hoặc bất kỳ thành phần nào khác.

Đừng quên rằng JSX biên dịch thành JS thông thường; trả về hai hàm không thực sự có ý nghĩa về mặt cú pháp. Tương tự như vậy, không đặt nhiều hơn một con trong một con chim nhạn.

Trong nhiều trường hợp, bạn có thể chỉ cần bọc mọi thứ trong một <div>hoặc một <span>.

Trong trường hợp của tôi, tôi muốn trả về nhiều <tr>s. Tôi bọc chúng trong một <tbody>- một bảng được phép có nhiều phần thân.

CHỈNH SỬA: Kể từ React 16.0, việc trả lại một mảng dường như được phép một lần nữa, miễn là mỗi phần tử có key: https://facebook.github.io/react/blog/2017/09/26/react-v16.0.html # new-render-return-type-fragment-and-string

CHỈNH SỬA: React 16.2 cho phép bạn bao quanh danh sách các phần tử bằng <Fragment>…</Fragment>hoặc thậm chí <>…</>, nếu bạn thích điều đó vào một mảng: https://blog.jmes.tech/react-fragment-and-semantic-html/


3
Bạn có thể làm gì nếu bạn muốn trả về nhiều <li>? Giả sử rằng tôi không thể chỉ quấn nó tất cả trong<ul>
Banjocat

@Banjocat Tôi e rằng tôi không biết: / Bạn được phép lồng các danh sách, vì vậy bạn có thể trả về một cái gì đó giống như <li><ul><li>one</li><li>two</li></ul></li>nếu điều đó hoạt động trong tình huống của bạn. Hoặc: Một div bao bọc sẽ không hoàn toàn hợp lệ nhưng có thể nó hiển thị tốt trong tất cả các trình duyệt có liên quan? Nếu bạn thử nó, hãy cho chúng tôi biết.
Henrik N

1
@Banjocat ... Tôi muốn biết câu trả lời tốt hơn cho câu hỏi của bạn. Có lẽ bạn nên đặt nó như một câu hỏi stackoverflow thông thường và xem liệu bạn có nhận được câu trả lời khác hay không.
user1175849,

@ user1175849 Có lẽ bạn có thể đăng câu hỏi đó sau đó :)
Henrik N

1
@HenrikN Fwiw, gói một "tập hợp con" litrong một spanhoặc divkhông hoạt động tốt đối với tôi. Div đã phá vỡ kết xuất một cách nghiêm trọng và, ít nhất là trong trường hợp sử dụng của tôi, khoảng cách này đã làm hỏng CSS. 2 ¢: Cố gắng trả về một số tập hợp con của lis là một mùi mã. Chúng tôi đang sử dụng một ulloại trình đơn kéo xuống và ban đầu tôi muốn nhiều thành phần trả về "phần" của lis. Cuối cùng, tốt hơn hết là đặt tất cả mã menu vào một thành phần duy nhất được "neo" tại ulhơn là đánh giày trong licác từ nhiều nguồn. Tôi nghĩ rằng nó cũng làm cho mô hình tinh thần cho giao diện người dùng sạch hơn một chút.
ruffin

13

Từ React v16.0.0 trở đi, có thể Trả lại nhiều phần tử bằng cách gói chúng trong mộtArray

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

Cũng từ React v16.2.0 , một tính năng mới được gọi React Fragmentslà được giới thiệu mà bạn có thể sử dụng để bao bọc nhiều phần tử

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

Theo tài liệu:

Một mẫu phổ biến trong React là cho một thành phần trả về nhiều phần tử. Các phân đoạn cho phép bạn nhóm một danh sách con mà không cần thêm các nút bổ sung vào DOM.

Các phân đoạn được khai báo với cú pháp rõ ràng có thể có khóa. Một trường hợp sử dụng cho việc này là ánh xạ một tập hợp thành một mảng các đoạn - ví dụ: để tạo danh sách mô tả:

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 là thuộc tính duy nhất có thể được chuyển cho Fragment. Trong tương lai, chúng tôi có thể thêm hỗ trợ cho các thuộc tính bổ sung, chẳng hạn như trình xử lý sự kiện.


7

Ngoài ra, bạn có thể muốn trả về một số mục danh sách trong một số hàm trợ giúp bên trong một thành phần React. Chỉ cần trả về một mảng các nút html với keythuộc tính:

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

Bạn có thể sử dụng createFragmenttại đây.

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

(sử dụng cú pháp ES6 và JSX tại đây)

trước tiên bạn phải thêm react-addons-create-fragmentgói:

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

Lợi thế so với giải pháp của Jan Olaf Krems: phản ứng không phàn nàn về sự thiếu sót key


sửa cho tôi nếu tôi sai nhưng bạn có thể chỉ cần thêm các phím theo cách thủ công. sử dụng ví dụ của jan: mục mảng đầu tiên nhận được ví dụ: <h3 key = {i}> </h3> và mục mảng thứ hai là sth hơi khác nhau như <p> key = {i + '-foo'}> </p>
nerdess

2

Đã cập nhật

Sử dụng React Fragment. Nó đơn giản. Liên kết đến tài liệu phân mảnh.

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

Câu trả lời cũ - lỗi thời

Với React> 16, bạn có thể sử dụng react-composite .

import { Composite } from 'react-composite';

// ...

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

Tất nhiên, phải cài đặt react-composite.

npm install react-composite --save

0

Nó đơn giản bởi mảnh 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>
        ),
      )}
    </>
  );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.