DrillLab
第 68 / 105 道68 / 105 · #338

什么是 Fragment

React Fragment

先自己答,再往下看Answer it yourself first

一句话:一个不产生真实 DOM 节点的容器, 用来满足「JSX 必须有单一根节点」的要求, 同时不往页面里多塞一层div

写法两种:<React.Fragment>和简写 <></>

为什么需要它(举得出场景才算答好):

  • 表格——<tr> 里套一层div非法 HTML, 浏览器会把它挪出去,布局直接坏。
  • Flex / Grid 布局—— 多一层 div打断父容器和子项的直接关系flex 属性全失效。
  • 减少 DOM 层数, 样式选择器也更好写。

会追问:「Fragment 上能加 key 吗?」——能,但必须用完整写法<React.Fragment key={id}>, 简写 <> 不支持任何属性。在列表里渲染多个兄弟元素时就得这么写, 这是简写唯一的限制。

In one line: a container that produces no real DOM node, so you can satisfy “JSX needs a single root” without pushing another div into the page.

Two forms: <React.Fragment> and the shorthand <></>.

Why you need it — you only answer this well with concrete cases:

  • Tables — a div inside a <tr> is invalid HTML; the browser hoists it out and the layout breaks on the spot.
  • Flex / Grid layouts — an extra div breaks the direct relationship between the container and its items, so every flex property stops working.
  • Fewer DOM levels, and easier style selectors.

Follow-up: “Can a Fragment take a key?” — yes, but only in the long form <React.Fragment key={id}>; the shorthand <> accepts no attributes at all. You need this whenever a list renders several sibling elements per item, and it is the shorthand’s only limitation.

JSXFragment 的两个真实场景示意Illustrative
1// ✗ tr 里多一层 div:非法 HTML,布局会坏
2<tr><div><td>A</td><td>B</td></div></tr>
3
4// ✓
5<tr><><td>A</td><td>B</td></></tr>
6
7// 列表里要 key,就不能用简写
8{rows.map((r) => (
9 <React.Fragment key={r.id}>
10 <dt>{r.term}</dt>
11 <dd>{r.desc}</dd>
12 </React.Fragment>
13))}
1// ✗ an extra div inside tr: invalid HTML, and the layout breaks
2<tr><div><td>A</td><td>B</td></div></tr>
3
4// ✓
5<tr><><td>A</td><td>B</td></></tr>
6
7// A list needs a key, so the short form cannot be used
8{rows.map((r) => (
9 <React.Fragment key={r.id}>
10 <dt>{r.term}</dt>
11 <dd>{r.desc}</dd>
12 </React.Fragment>
13))}