React TS - Children props Type
React children props 型別
容易混淆的各種寫法
JSX.Element
: 陣列(多個元素)無法使用JSX.Element | JSX.Element[]
: strings 無法使用React.ReactNode
: 任何元素都接受,例如:JSX、string、number 等React.ReactChildren
: 接受多個 children,不接受單一 childrenReact.ReactChild[]
: 不適合使用,這是一個效用函式(Utility function)React.ReactElement
: 接受 React 元件
// 使用 React.ReactNode(不限定元素)
import React, { ReactNode, ReactElement } from "react";
type BoxProps = { children: ReactNode };
function MyComponent({ children }: BoxProps) {
return <div>{children}</div>;
}
// 倘若希望限制為 react 元件,則可以使用 ReactElement
interface MyComponentProps {
children: ReactElement; // 期望子元素是React元素
}
function MyComponent({ children }: MyComponentProps) {
return <div>{children}</div>;
}
最好是直接使用 React 定義好的 PropsWithChildren
type PropsWithChildren<P = unknown> = P & {
children?: ReactNode | undefined;
};
倘若希望擴展 props 的型別定義(props 包括 children),則可以使用 extend
import React, { PropsWithChildren } from "react";
interface MyComponentProps extends PropsWithChildren {
// 其他 props
color: string;
}
function MyComponent({ children, color }: MyComponentProps) {
return <div style={{ color: color }}>{children}</div>;
}
Built-in helpers
React.PropsWithChildren
React.ComponentPropsWithoutRef
FunctionalComponent<Props>
(React 18 之前適用)React.HTMLProps
React.ComponentPropsWithoutRef
是一个 React 型別,用於取得组件的 props,但不包括 ref
import { ComponentPropsWithoutRef } from "react";
type ButtonProps = ComponentPropsWithoutRef<"button">;
function MyComponent(props: ComponentPropsWithoutRef<"button">) {
return <button {...props}>Click me</button>;
}
React.HTMLProps
是 React 型別,用於取得 HTML 元素的 props
import { HTMLProps } from "react";
interface MyButtonProps extends HTMLProps<HTMLButtonElement> {
// 自定義 props
color: string;
}
// 將button標籤的屬性傳下去
function MyButton({ color, ...rest }: MyButtonProps) {
return <button style={{ backgroundColor: color }} {...rest} />;
}
注意:React 18 之前可以使用
FunctionalComponent<Props>
,但 React18 之後被移除了
import * as React from "react";
// 🚨 No good anymore.
const Input: React.FC = ({ children }) => <div>{children}</div>;