React.Fragment 和 <></>

写代码的时候,遇到了只能使用 React.Fragment 的场景,想着记录下它和 <></> 的用法和区别

发布于  星期二,三月 19 2024

介绍

<></> 其实是 React.Fragment 的语法糖,它们两个都可以用来对元素进行分组,渲染成 HTML 后不会增加额外的标签

举个例子:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <header>Header</header>
    <main>Main</main>
    <footer>Footer</footer>
  </body>
</html>

翻译成 jsx

// ✅ 1. 正确写法:
export default function App() {
  return (
    <React.Fragment>
      <header>Header</header>
      <main>Main</main>
      <footer>Footer</footer>
    </React.Fragment>
  );
}

// ✅ 2. 正确写法:better
export default function App() {
  return (
    <>
      <header>Header</header>
      <main>Main</main>
      <footer>Footer</footer>
    </>
  );
}

下面这个不行

// ❌ 错误写法:
export default function App() {
  return (
      <header>Header</header>
      <main>Main</main>
      <footer>Footer</footer>
  );
}

上面 👆 写法会报错:

JSX expressions must have one parent element.

这是因为在 jsx 中至少需要一个根元素,那在外面包一层 div 呢?这样

export default function App() {
  return (
    <div>
      <header>Header</header>
      <main>Main</main>
      <footer>Footer</footer>
    </div>
  );
}

在外包一层 div 的做法可以是可以,但是渲染出来的 HTML 结构会多包含一个 div,不推荐🙅‍♂️

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
     <!-- 多出来一个 div 标签,是不是有点别扭,本来好好的结构被破坏了 -->
    <div>
      <header>Header</header>
      <main>Main</main>
      <footer>Footer</footer>
    </div>
  </body>
</html>

遇到需要对元素进行分组但又不想引入额外的 HTML 标签时,就可以使用 React.Fragment 或者 <></>

区别

React.Fragment 和 <></> 二者的唯一区别就是 React.Fragment 可以设置 key 而 <></> 设置不了

在 jsx 遍历元素,需要设置 key 时,只能用 React.Fragment,不能用 <></>

<BreadcrumbList>
  {linkList.map((el) => (
    // 需要设置 key时,只能使用 React.Fragment
    <React.Fragment key={el}>
      <BreadcrumbItem>
        <BreadcrumbLink>
          <Link href={el}>{PATHS_MAP[el]}</Link>
        </BreadcrumbLink>
      </BreadcrumbItem>
      <BreadcrumbSeparator />
    </React.Fragment>
  ))}
  <BreadcrumbItem>
    <BreadcrumbPage>
        {PATHS_MAP[labelLink]}
    </BreadcrumbPage>
  </BreadcrumbItem>
</BreadcrumbList>

Tips

  • 一般情况,应该优先使用 React.Fragment 或者 <></>,这样可以避免不必要的 div 节点,可以让渲染出来的 HTML 结构清晰简洁。

  • 使用 <></>时,不要忘记导入 React

    • React 版本 > 17 时,可以不用导入

    jsx-fn.png

    • React 版本 16.x 时,需要手动导入

    react-classic.png

    import React from 'react';
    
  • React