Fragments
是一個實戰上非常常使用的技巧,它可以讓我們在寫 React 的時候,可以不用一定要包一層 div
,這樣就可以讓我們的 HTML 結構更加乾淨,那麼該怎麼使用呢?讓我們一起來看看吧!
在說明為什麼要使用 Fragments
之前,我們先來看看一個簡單的範例:
const App = () => {
return (
<div>
<h1>Fragments Sample</h1>
<h1>Fragments Sample</h1>
</div>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
上面是一個很簡單的範例,我們以往開發都會用一個 <div>
包著內層,因為如果你外層不額外包一層的話,就會發生錯誤,什麼錯誤呢?讓我們來看看
const App = () => {
return (
<h1>Fragments Sample</h1>
<h1>Fragments Sample</h1>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
基本上你是可以看到 CodePen 直接跳出一個提示訊息
Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?
那麼為了解決這個問題,我們可能就會如同一開始範例那樣子使用一個 <div>
包著內層,但是這樣子的話,我們的 HTML 結構就會莫名多一個沒意義的 <div>
,當專案越來越龐大時,這個沒有意義的 <div>
就會讓我們的 HTML 結構變得非常雜亂,因此 React 就提供了一個神兵利器 Fragments
,讓我們可以不用一定要包一層 <div>
,這樣就可以讓我們的 HTML 結構更加乾淨
const App = () => {
return (
<React.Fragment>
<h1>Fragments Sample</h1>
<h1>Fragments Sample</h1>
</React.Fragment>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
當你使用 React.Fragment
之後你也可以發現原本的錯誤訊息就不見了,而且你的 HTML 結構也變得乾淨許多,這邊我們也可以來觀看 HTML 的結構是不是真的少了莫名其妙的 <div>
相信兩者比較下來,你應該會比較喜歡 React.Fragment
。
那麼 React.Fragment
其實還有簡寫的方式,就是使用 <>
,這樣子你寫起來可以更愉快
const App = () => {
return (
<>
<h1>Fragments Sample</h1>
<h1>Fragments Sample</h1>
</>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
那麼有沒有發現 React.Fragment
與 Vue 的 <template>
有點像呢?Vue 的 <template>
也是用來包裝多個元素,但是不會在 HTML 結構中產生多餘的元素,讓我們回顧一下 Vue 的 <template>
是如何使用的
<div id="app">
<template v-if="true">
<h1>Template Sample</h1>
<h1>Template Sample</h1>
</template>
</div>
const { createApp } = Vue;
const app = createApp({
setup() {
}
});
app.mount('#app');
我們可以看到 Vue 的 <template>
也是不會在 HTML 結構中產生多餘的元素
前面有提到 <></>
是 React.Fragment
的簡寫,而它也有自己的名稱也就是 Empty Tag,這個名稱是因為它是一個空標籤。
<></>
與 React.Fragment
有什麼差異呢?一般狀況下兩者是沒有什麼太大差異的
const App = () => {
return (
<>
<h1>Empty Sample</h1>
<h1>Empty Sample</h1>
</>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
const App = () => {
return (
<React.Fragment>
<h1>Empty Sample</h1>
<h1>Empty Sample</h1>
</React.Fragment>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
但我們通常在跑一段迴圈時,通常 React 會提示你要補上 key
,而這時候你就不可以使用 Empty tag,因為 Empty tag 是沒有 key
與 attribute
(屬性) 的,所以你必須使用 React.Fragment
來包著,並將 key
寫在 React.Fragment
上
const App = () => {
const list = [1, 2, 3, 4, 5];
return (
<>
{list.map((item, index) => (
<React.Fragment key={index}>
<h1 key={index}>{item}</h1>
</React.Fragment>
))}
</>
)
}
const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);
所以這邊我才沒有特別說明 Empty tag 是 React.Fragment
的語法糖,因為它們在使用上有一些差異。
本文將會同步更新到我的部落格