Làm cách nào để hiển thị các phần tử anh chị em mà không cần gói chúng trong thẻ cha?


82

Trong hầu hết các trường hợp, có thẻ mẹ không phải là một vấn đề.

React.createClass({
    render: function() {
        return (
            <tbody>
                <tr><td>Item 1</td></tr>
                <tr><td>Item 2</td></tr>
            </tbody>
        );
    }
});

Nhưng có một số trường hợp có ý nghĩa khi có các phần tử anh chị em trong một hàm hiển thị mà không có phần tử cha, và đặc biệt trong trường hợp bảng, bạn không muốn bọc một hàng bảng trong một div.

React.createClass({
    render: function() {
        return (
            <tr><td>Item 1</td></tr>
            <tr><td>Item 2</td></tr>
        );
    }
});

Ví dụ thứ hai cung cấp cho các lỗi sau: Adjacent XJS elements must be wrapped in an enclosing tag while parsing file.

Làm cách nào để tôi có thể hiển thị hai phần tử anh em mà không bao bọc chúng trong một <div>hoặc một cái gì đó tương tự?


3
Tôi dường như luôn gặp khó khăn khi tìm câu hỏi / câu trả lời này nên tôi quyết định tự hỏi / trả lời nó. Giải thích / câu trả lời bổ sung được hoan nghênh.
thealexbaron

Một ví dụ khác là các mục điều hướng
Tjorriemorrie

Câu trả lời:


66

Đây là một hạn chế hiện tại, nhưng có thể sẽ được khắc phục vào một thời điểm nào đó trong tương lai ( có một số vấn đề còn mở trên github repo ).

Hiện tại, bạn có thể sử dụng một hàm trả về một mảng (về cơ bản đây là một thành phần không trạng thái):

function things(arg, onWhatever){
    return [
        <tr><td>Item 1</td></tr>,
        <tr><td>Item 2</td></tr>
    ];
}

Và sử dụng nó trong thành phần của bạn.

return (
    <table><tbody>
      {things(arg1, this.handleWhatever)}
      {things(arg2, this.handleWhatever)}
    </tbody></table>
);

Cập nhật

Trong React 16, bạn sẽ có thể trả về một mảng từ kết xuất.

Cập nhật khác

Bây giờ bạn có thể trả về một mảng cấp cao nhất hoặc sử dụng <React.Fragment>.

Với một mảng, chúng ta cần đặt một khóa trên mỗi mục, vì React không biết rằng hai phần tử là không đổi, thay vì một danh sách được tạo động:

function RowPair() {
  return [
    <tr key="first"><td>First</td></tr>,
    <tr key="second"><td>Second</td></tr>,
  ]
}

Với React.Fragment, nó hoạt động giống như gói nó trong một <div>hoặc tương tự, nơi keykhông bắt buộc phải có nếu chúng ta không xây dựng các con một cách năng động. Đầu tiên, chúng ta có thể bọc mảng trong một Fragment:

function RowPair() {
  return <React.Fragment>{[
    <tr key="first"><td>First</td></tr>,
    <tr key="second"><td>Second</td></tr>,
  ]}</React.Fragment>
}

Và sau đó chúng ta có thể loại bỏ keyhoàn toàn mảng và s:

function RowPair() {
  return <React.Fragment>
    <tr><td>First</td></tr>
    <tr><td>Second</td></tr>
  </React.Fragment>
}

2
Tại sao tất cả mọi người nói điều này hiệu quả ???? Lỗi chưa tìm thấy: x.render (): Phần tử React hợp lệ (hoặc null) phải được trả lại. Bạn có thể đã trả về không xác định, một mảng hoặc một số đối tượng không hợp lệ khác.
Xogle

@Xogle Chắc hẳn có gì đó đã thay đổi trong API React. Dường như không hoạt động nữa.
Petr Peller

1
@FakeRainBrigand Tôi thấy vấn đề. Nó không phải là một "thành phần không trạng thái" mà là một hàm trả về một mảng. Các thành phần không trạng thái không thể trả về mảng và bạn không thể kết nối một hàm đơn giản với cửa hàng Redux.
Petr Peller

@PetrPeller bạn có đang sử dụng jsx không? Trong ví dụ, tôi gọi nó giống như một hàm.
Brigand

Tôi không hiểu tất cả các phiếu ủng hộ - điều này hoàn toàn không trả lời được câu hỏi. Câu hỏi đặt ra là làm thế nào để hiển thị các phần tử anh chị em mà không có phần tử cha và câu trả lời này vẫn hiển thị một phần tử cha.
Dancrumb

33

Tôi biết đây là một bài viết cũ, nhưng có lẽ câu trả lời của tôi có thể giúp ích cho những người mới như tôi.

Trong React 16.2, hỗ trợ được cải thiện cho Fragment đã được thêm vào.

Bây giờ bạn có thể trả lại nó như thế này:

return (
  <>
    <tr><td>Item 1</td></tr>
    <tr><td>Item 2</td></tr>
  </>
);

Bạn có thể bọc nó bằng <></>hoặc<Fragment></Fragment> .

Nếu bạn muốn chuyển một số thuộc tính, chỉ có khóa được hỗ trợ tại thời điểm viết bài và bạn sẽ phải sử dụng <Fragment />vì cú pháp ngắn<></> không chấp nhận các thuộc tính.

Lưu ý: Nếu bạn định sử dụng cú pháp ngắn, hãy đảm bảo rằng bạn đang sử dụng Babel 7 .

Nguồn tham khảo


1
Chính xác những gì tôi đã theo sau, cảm ơn! Ngoài ra, đề phòng bất kỳ ai khác cần nó: nhập React, {Fragment} từ 'react'
Chris

Tôi dường như không thể tìm thấy việc triển khai Fragmenttrong kho của họ, ai đó có thể chỉ cho tôi được không? Cảm ơn :)
Ramon Balthazar

Tôi không thể làm cho nó hoạt động, ngay cả khi tôi cài đặt Babel-cli ... thậm chí chỉ cho giải pháp <>. Làm thế nào có thể @onoya Tôi sẽ đăng một chủ đề sớm,
Gaelle


3

Có một phần tử cha là hữu ích trong hầu hết các trường hợp, chẳng hạn như bạn có thể có một className cha có thể nhắm mục tiêu kiểu phần tử con và một vài trường hợp khác ...

Tuy nhiên, nếu bạn thực sự không muốn làm điều đó, bạn có thể sử dụng React.Fragment

Vì vậy, chỉ cần làm một cái gì đó như sau:

<React.Fragment>
  <First />
  <Second />
  <Third />
</React.Fragment>

Từ phiên bản 16.2 , có một phiên bản rút gọn cũng được sử dụng <>, trông giống như thế này trong chức năng kết xuất:

render() {
  return (
    <>
      <First />
      <Second />
      <Third />
    </>
  );
}

Ngoài ra, nếu sử dụng phiên bản 16.0 trở lên, bạn có thể trả về mảng các phần tử không cần trình bao bọc chính như bên dưới:

render() {
 return [
  <h1 key="heading">Hello from Alireza!</h1>,
  <p key="first">Here where I'm!</p>,
  <p key="second">And again here :)</p>
 ];
}

0

Bạn có thể quấn nó vào dấu ngoặc như sau:

React.createClass({
    render: function() {
        return (
          [
            <tr><td>Item 1</td></tr>
            <tr><td>Item 2</td></tr>
          ]
        );
    }
});

Làm thế nào về nếu bạn cũng cần sử dụng Object.keys()trong vòng trở lại?
Juha Untinen

Ví dụ. return ( [ <tr><td>Header</td></tr>{ Object.keys(this.props.data).map(function(item) { <tr><td>{data}</td></tr> }) } ] ); Với 15.4.2, nó mang lại Unexpected token, expected ,trong khung mở trong sự trở lại
Juha Untinen

hãy thử một cái gì đó như sau: return ({Object.keys (this.props.data) .map (function (item) {<tr><td>{data}</td> </tr>}). unshift ({< tr> <td> Đầu trang </td> </tr>})});
Vitaliy Andrusishyn

Điều này không làm việc, vẫn cần phải có một dấu phẩy tách <tr> -s
Philipp Munin

0

Ví dụ này hoạt động tốt đối với tôi:

let values = [];

if (props.Values){
  values = [
    <tr key={1}>
      <td>props.Values[0].SomeValue</td>
    </tr>
  ,
    <tr key={2}>
        <td>props.Values[1].SomeValue</td>
        </tr>
    ];
}

return (
    <table className="no-border-table table">
      <tbody>
        <tr>
            <th>Some text</th>
        </tr>
        {values}
      </tbody>
    </table>
)

0

Một cái gì đó giống như cú pháp này đã làm việc cho tôi

this.props.map((data,index)=>{return( [ <tr>....</tr>,<tr>....</tr>];)});

-2

Đối với những người sử dụng TypeScript, cú pháp chính xác là:

return [
  (
    <div>Foo</div>
  ),
  (
    <div>Bar</div>
  )
];

1
Đây là giống với câu trả lời bằng @thealexbaron và nó không có gì để làm với nguyên cảo
andrewarchi
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.