React 踩坑:忘记使用 React.Fragment 进行返回

—— 从「多余 DOM」到「Syntax Error」的 3 分钟急救

当你在 React 函数组件里写下:

return (
  <div>A</div>
  <div>B</div>   // ❌ JSX 语法错误:Adjacent JSX elements must be wrapped in an enclosing tag
);

或 ESLint 提示:

JSX expressions must have one parent element.

React 告诉你:「必须返回单一根元素」
本文用「场景 → 修复 → 性能对比」三步法,一次性掌握 React.Fragment 的正确姿势。


一、为什么必须“单根”?

JSX 编译后:

return React.createElement(
  'div', null,
  React.createElement('div', null, 'A'),
  React.createElement('div', null, 'B')
);

createElement 第一参数只能是单个元素或 Fragment,否则语法树无法生成。


二、3 个高频翻车现场 & 修复

1️⃣ 相邻元素直接 return(语法错误)

function Items() {
  return (
    <li>Apple</li>
    <li>Banana</li>   // ❌ 相邻元素
  );
}

修复 1:显式 <React.Fragment>(兼容所有版本)

import React from 'react';
function Items() {
  return (
    <React.Fragment>
      <li>Apple</li>
      <li>Banana</li>
    </React.Fragment>
  );
}

修复 2:简写 <>(React 16.2+)

function Items() {
  return (
    <>
      <li>Apple</li>
      <li>Banana</li>
    </>
  );
}

2️⃣ 循环返回数组却忘 key

function List({ items }) {
  return items.map(item => <li>{item}</li>); // ❌ 缺少 key
}

修复:Fragment + key

return items.map(item => (
  <React.Fragment key={item.id}>
    <li>{item.name}</li>
  </React.Fragment>
));

3️⃣ 条件渲染多根节点

function Status({ isLoading, data }) {
  if (isLoading) return <Spinner />;
  return <div>{data}</div>;   // ✅ 单根,OK
  // ❌ 若写成:
  // return <Spinner /><div>{data}</div>;  // 语法错误
}

修复:Fragment 包裹

return (
  <>
    {isLoading && <Spinner />}
    {!isLoading && <div>{data}</div>}
  </>
);

三、性能对比(DevTools Profiler)

写法DOM 节点重渲染次数
外层 <div>+1 包裹节点1
<> / <Fragment>0 额外节点1(无变化)

Fragment 不会生成任何真实 DOM,避免「包裹层污染」。


四、特殊场景:需要 keyref

  • 列表循环 → 用显式 <React.Fragment key={id}>
  • 需要 ref → 用 <React.Fragment ref={ref}>(React 18.3+)
return items.map(item => (
  <React.Fragment key={item.id} ref={itemRef}>
    <li>{item.name}</li>
  </React.Fragment>
));

五、一句话总结

「多根必包」——用 <><React.Fragment> 包裹相邻 JSX,
既不增加 DOM,又让 React 编译顺利通过。


最后问候亲爱的朋友们,并邀请你们阅读我的全新著作

📚 《 React开发实践:掌握Redux与Hooks应用 》

在这里插入图片描述

更多推荐