2-13 JSX 元素只能有一個最外層元素

這個單元中,將進一步說明,之前曾提到過的「一個 JSX 元素只能有一個最外層元素」是指什麼意思。以下面的例子來說,在 Counter 這個元件的 JSX 中,只有一個根節點,就是最外層的 <div className"container">...</div>

const Counter = () => <div className="container">{/* ... */}</div>;

錯誤寫法#

但若我們在這個 JSX 元素中,放入另一個節點 <div class="other-container">...</div> 的話,是不被允許的:

// ❌ 這是不被允許的
const Counter = () => (
<div class="container">
{/* ... */}
</div>
<div class="other-container">
{/* ... */}
</div>
);

正確做法一:外層的包一個 HTML Tag#

如果需要的話,外層可以多包一個 HTML 標籤,例如 <div> ,這樣這個 JSX 元素的最外層仍然只有一個根節點:

// 外層多包一個 `<div>`
const Counter = () => (
<div>
<div class="container">{/* ... */}</div>
<div class="other-container">{/* ... */}</div>
</div>
);

正確做法二:使用 React Fragment#

但有些時候,你不希望這些元素外層還要額外包一個 HTML 標籤,這時 React 提供了一個 <React.Fragment> 的標籤讓你使用,寫起來會像這樣:

const Counter = () => (
<React.Fragment>
<div class="container">{/* ... */}</div>
<div class="other-container">{/* ... */}</div>
</React.Fragment>
);

如此,就可以解決 JSX 外層元素只能有一個根節點的情況,同時當我們透過瀏覽器的 console 視窗來檢視時,原本的 HTML 元素外層不會再被多包一個 <div> 標籤(畫面左側 #root 裡面多了一個 <div>):

imgur

由於開發者大多很懶惰簡潔,能用簡短而清楚的方式來表達意思自然是最好不過的,因此,<React.Fragment> 還可以縮寫成 <>,蛤?你問我縮寫成什麼?就是 <>,沒錯,你不需要再寫落落長的 <React.Fragment></React.Fragment>,只需要寫 <></>,像這樣:

// <></> 是 <React.Fragment></React.Fragment> 的縮寫
const Counter = () => (
<>
<div class="container">{/* ... */}</div>
<div class="other-container">{/* ... */}</div>
</>
);

所以未來如果你看到有 JSX 元素是直接使用 <>...</> 包起來的話,也不要感到太過訝異!