理解ReactNode、JSX.Element 和 ReactElement 的正确用法

更新日期: 2025-08-23 阅读: 849 标签: 类型

在使用 react 和 TypeScript 开发项目时,很多人都会遇到类型报错的问题。满屏的“类型不匹配”红线不仅打断思路,也让人感到困扰。如果你也曾为ReactNode、JSX.Element 和 ReactElement 这几个类型的选择而纠结,这篇文章或许能帮你理清思路。

先说结论:组件的 props,尤其是 children,建议使用 React.ReactNode;而组件的返回值类型,则应使用 JSX.Element。React.ReactElement 通常只用于一些更复杂或底层的场景。


一、三种类型的简单区别

先看两个例子:

const node: JSX.Element = <p />;  // ✅ 正确,只能接受 JSX
const node2: React.ReactNode = "Hello" || 42 || <p />; // ✅ 正确,可接受多种类型

  • JSX.Element 是一个比较严格的类型,通常用于描述组件的返回内容。

  • React.ReactNode 则宽松很多,可以表示任何可以被 React 渲染的内容,包括字符串、数字、布尔值、null、undefined 或 JSX 元素。

因此,在声明组件的 props,特别是 children 时,使用 ReactNode 是更合适的选择:

interface Props {
  children: React.ReactNode; // ✅ 推荐写法
}

const Component: React.FC<Props> = ({ children }) => <p>{children}</p>;

如果你错误地将 children 定义为 JSX.Element,那么像 <Component>Hello</Component> 这样的写法就会报错,因为字符串不被视为 JSX.Element。

简单总结:props 尤其是内容型 prop 用 ReactNode,组件返回值用 JSX.Element。


二、为什么推荐这样使用?

TypeScript 最初并不支持 JSX语法,后来通过 .tsx 文件和 tsconfig 中的 jsx 选项才实现兼容,并逐渐形成了当前这一套类型系统。

  1. JSX.Element:用于约束返回类型

很多人习惯将 children 定义为 JSX.Element,这其实限制过大。因为 React 不仅可以渲染 JSX,还能渲染字符串、数字、null 等原始类型。

JSX.Element 实际上是一个扩展自 ReactElement 的接口,大致结构如下:

declare global {
  namespace JSX {
    interface Element extends React.ReactElement<any, any> {}
  }
}

因此,它最适合用于组件的返回类型,例如:

const MyComponent = (): JSX.Element => <p>Hello</p>;

但不适用于需要灵活内容的 props。

  1. React.ReactNode:更灵活的内容类型

ReactNode 的设计初衷就是涵盖所有可渲染的内容,其类型定义包括:

type ReactNode = 
  | ReactElement 
  | string 
  | number 
  | boolean 
  | null 
  | undefined 
  | ReactNodeArray;

因此它特别适合用于接收动态内容,比如 children、标题、页脚等:

interface CardProps {
  title: React.ReactNode;
  extra?: React.ReactNode;
  children: React.ReactNode;
}

这样定义之后,无论是传递文字、数字还是 JSX,TypeScript 都不会报错。

  1. React.ReactElement:底层元素对象

ReactElement 类型描述的是 JSX 编译后的元素对象结构,包含 type 和 props 等属性。它通常在工具函数或高阶组件中使用,用于直接操作元素结构。

例如:

function mapChildren(children: React.ReactElement[]): React.ReactElement[] {
  return children.map(child => {/* 处理逻辑 */});
}

在日常业务组件中,一般不需要直接使用这个类型。


三、一张表格总结使用场景

类型适用场景例子
React.ReactNodechildren 或其他内容型 props<p>{123}</p>, <Title text="Hello" />
JSX.Element函数组件的返回值const Comp = (): JSX.Element => <p />;
React.ReactElement操作元素结构或工具函数cloneElement(element, newProps)


四、实际代码建议

  • children 基本上总是应该写成 React.ReactNode。

  • 组件的返回类型推荐明确标注为 JSX.Element,有助于代码检查和团队协作。

  • 除非你明确要处理元素对象,否则不要使用 React.ReactElement。

如果在编写过程中遇到类型错误,可以先问自己:我是在传递内容,还是在声明返回类型?如果是传递内容,选 ReactNode;如果是返回类型,就用 JSX.Element。


五、总结

只要记住一个原则:props 用 ReactNode,返回值用 JSX.Element,就能避免大部分类型错误。ReactElement 仅用于少数高级场景。合理运用这些类型,不仅能减少报错,还能让代码更清晰、更易于维护。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/12896

相关推荐

Js如何将String转化为Int

字符串到整型的一个转换,在面试过程中或者在工作中都会频繁遇到,那么string到js怎么转换呢 ?parseInt方法在format\'00\'开头的数字时会当作2进制转10进制的方法进行转换

Typescript内置类型与自定义类型

大家用过 Typescript 都清楚,很多时候我们需要提前声明一个类型,再将类型赋予变量。例如在业务中,我们需要渲染一个表格,往往需要定义:

Js实现base64,file和blob相互转换

JavaScript实现base64,file和blob相互转换:base64转为Blob;Blob转为base64;base64转换为file;js图片转换为base64;在Java中base64和File相互转换

Js的6种基本数据类型

在JS中一共有六种数据类型 String:字符串 Number:数值 Boolean:布尔值 Null:空值 Undefined:未定义 Object:对象 ,其中String,Number,Boolean,Null,Undefined属于基本数据类型而Object属于引用数据类型

JavaScript判断字符串是否为数字类型

JavaScript中有Number.isInteger可以判断一个字符串是否为整数。不过目前JS没有内置的函数来判断一个数字是否为包含小数的数字:

TypeScript never 类型

在类型理论(数学逻辑中的一种理论)中, 底部类型 是没有值的类型。也称为零或空类型,有时用 falsum(⊥)表示。 数学理论与计算机的发展是相辅相成的,底部类型在计算机科学中也有一定的应用场景。

JS数据类型转换表

下表显示了将不同的JavaScript值转换为Number,String和Boolean的结果:注意:引号(\\\"\\\")中的值表示字符串值。在红色的值是程序员可能不希望被转换为的值。

Js的typeof返回哪些数据类型?

JavaScript中的数据类型:值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。引用数据类型:对象(Object)、数组(Array)、函数(Function)。

为你的 JavaScript 项目添加智能提示和类型检查

近在做项目代码重构,其中有一个要求是为代码添加智能提示和类型检查。智能提示,英文为 IntelliSense,能为开发者提供代码智能补全、悬浮提示、跳转定义等功能,帮助其正确并且快速完成编码。

JS中的布尔 数字 字符串

JS中所有的值都可以转换成布尔类型 使用Boolean()或者 !!(两个感叹号),JS中所有的值都可以转换成数字类型,使用Number()或+。数字类型转换场景目的只有一个,用于计算,将后台传递的数据,从字符串转换为数字并参与计算

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!