⚛️ 揭秘 React 的类型:组件类型

2025-05-25

⚛️ 揭秘 React 的类型:组件类型

React 的类型系统与 TypeScript 结合使用,为开发者构建类型安全的应用程序提供了一个强大的框架。了解各种 React 类型之间的细微差别,对于做出明智的使用决策至关重要。让我们深入比较这些类型,了解它们之间的区别以及合适的用例。

1️⃣ React.FC 与 React.ElementType

React.FC(React.FunctionComponent)

React.FC是 React 中专门用于定义函数组件的类型。随着 React Hooks 的引入和广泛采用,它开始变得越来越流行。

在 React 18 之前,它包含一个隐式childrenprop,这使得它适合预期有子组件的组件。然而,长期以来,隐式childrenprop 类型已根据React 18 的类型变更被移除。

以下是使用示例:



interface SomeComponentProps {
  title: string;
  children?: React.ReactNode;
}

export const SomeComponent: React.FC<SomeComponentProps> = ({ title, children }) => {
  return (
    <article>
      <h2>{title}</h2>

      {children}
    </article>
  );
};


Enter fullscreen mode Exit fullscreen mode

然而,自从删除了隐式childrenprop 类型后,使用它的人就少了很多,React.FC因为它很笨重,而且与直接将接口分配给 props 对象相比,没有提供任何真正的好处:



interface SomeComponentProps {
  title: string;
  children?: React.ReactNode;
}

export const SomeComponent = ({ title, children }: SomeComponentProps) => {
  return (
    <article>
      <h2>{title}</h2>

      {children}
    </article>
  );
};


Enter fullscreen mode Exit fullscreen mode

React.ElementType

React.ElementType另一方面, 是一种更广泛的类型,表示任何可由 React 渲染的组件类型。这不仅包括 React 函数式组件和类组件,还包括 HTML 元素的字符串标签(例如“div”、“span”)。React.ElementType当你想接受一个组件作为 prop 并渲染它时,它特别有用,从而允许动态使用组件。



const DynamicComponent: React.ElementType = 'div';

export const Container = () => (
  <DynamicComponent className="container">Hello, world!</DynamicComponent>
);


Enter fullscreen mode Exit fullscreen mode

这里,DynamicComponent被输入为React.ElementType,允许它被动态地分配给不同类型的组件或 HTML 元素。

比较笔记

  • React.FC主要用于定义函数式组件。从 React 18 开始,它就不再那么有用了。
  • React.ElementType在接受各种可渲染实体方面提供了更大的灵活性。React.ElementType当你需要动态接受不同类型的 React 组件或 HTML 元素时使用。

2️⃣ React.ReactNode、React.ReactElement 和 JSX.Element 的比较

React.ReactElement

React.ReactElement是一个由函数创建的对象,具有typepropskey属性React.createElement()。与 相比,它是一种更具体的类型React.ReactNode,表示可由 React 直接渲染的元素。



const elementContent: React.ReactElement = <div>Hello, React.ReactElement!</div>;

export const Container = () => <>{elementContent}</>;


Enter fullscreen mode Exit fullscreen mode

React.ReactNode

React.ReactNode是最具包容性的类型,表示任何可被 React 渲染的内容。这包括原始类型(字符串、数字、布尔值)、JSX.Elements、React.ReactElements、这些类型的数组等等。它是 props 的首选类型,可以接受各种各样的内容,例如children



const multiElementContent: React.ReactNode = (
  <div>
    <p>This is a paragraph.</p>
    {'This is a text node.'}
    {null}
  </div>
);

const primitiveTypeContent: React.ReactNode = "I'm a primitive-type React.ReactNode";

export const Container = () => {
  return (
    <>
      {multiElementContent}
      {primitiveTypeContent}
    </>
  );
};


Enter fullscreen mode Exit fullscreen mode

React.ReactNode下面的维恩图描述了和之间的关系React.ReactElement

React.ReactNode 与 React.ReactElement

JSX.元素

JSX.Element本质上是React.ReactElement一个定义更广的类型,允许各种库以自己的方式实现 JSX。它是 TypeScript 内部使用的类型,用于表示 JSX 表达式的返回类型。



const jsxElement: JSX.Element = <span>Hello, JSX.Element!</span>;

export const Container = () => <>{jsxElement}</>;


Enter fullscreen mode Exit fullscreen mode

比较笔记

  • React.ReactNode是最灵活和包容的,适合像小孩子这样可以接受多样化内容的打字道具。
  • React.ReactElement并且JSX.Element更加具体,React.ReactElement适用于 React 创建的元素和JSX.Element使用 JSX 语法定义的元素。

💡 有趣的事实

  • 函数组件的返回值,也就是渲染过程的结果,总是React.ReactNodeReact.ReactElement/ JSX.Element。基本上,函数组件可以理解为:


type ReactFC<P = {}> = (props: P) => React.ReactNode;


Enter fullscreen mode Exit fullscreen mode
  • 像任何常规函数一样调用函数组件会得到与使用 JSX 语法相同的结果,这意味着:


const MyComponent = ({ children }: { children: React.ReactNode }) => {
  return <div>{children}</div>;
};

export const App = () => {
  return (
    <div>
      <MyComponent>
        Rendering MyComponent with <strong>JSX Syntax</strong>
      </MyComponent>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

与以下内容相同:



const MyComponent = ({ children }: { children: React.ReactNode }) => {
  return <div>{children}</div>;
};

export const App = () => {
  return (
    <div>
      {MyComponent({
        children: (
          <>
            Rendering MyComponent by&nbsp;
            <strong>Invoking Function Component</strong>
          </>
        ),
      })}
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

查看下面的 codesandbox 了解演示:

🏁 结论

了解这些 React 类型和接口之间的差异,可以帮助开发者做出更明智的决策,从而编写更简洁、更易于维护的代码。无论是定义组件、接受动态内容还是处理子元素,选择正确的类型对于充分发挥 React 和 TypeScript 的潜力都至关重要。

如果您想了解如何最佳地组织 React 组件中的代码,请务必查看这篇文章:

请期待我即将发表的文章,深入探讨利用这些类型的理解的模式。


如果您对前端开发和 Web 开发感兴趣,请关注我并查看下面个人资料中我的文章。

文章来源:https://dev.to/itswillt/explaining-reacts-types-940
PREV
⚛️ Folder Structures in React Projects
NEXT
⚛️ 在 React 中应用策略模式(第一部分)