React 的類型系統與 TypeScript 一起使用時,為開發人員提供了建構類型安全應用程式的強大框架。了解各種 React 類型之間的細微差別對於就其使用做出明智的決策至關重要。讓我們深入詳細比較這些類型,以了解它們的差異和適當的用例。
React.FC
是React中專門用來定義函數元件的類型。當 React Hooks 被引入並廣泛採用時,它開始變得更加流行。
在 React 18 之前,它曾經包含一個隱式的children
屬性,使其適合預期有孩子的元件。但很長一段時間以來,隱式的children
prop類型已經根據React 18的類型變化被刪除了。
這是一個使用範例:
interface SomeComponentProps {
title: string;
children?: React.ReactNode;
}
export const SomeComponent: React.FC<SomeComponentProps> = ({ title, children }) => {
return (
<article>
<h2>{title}</h2>
{children}
</article>
);
};
然而,由於刪除了隱children
prop 類型,現在使用React.FC
的人少了很多,因為與直接將介面分配給 props 物件相比,它很笨重並且沒有提供任何真正的好處:
interface SomeComponentProps {
title: string;
children?: React.ReactNode;
}
export const SomeComponent = ({ title, children }: SomeComponentProps) => {
return (
<article>
<h2>{title}</h2>
{children}
</article>
);
};
另一方面, React.ElementType
是一種更廣泛的類型,表示可以由 React 呈現的任何元件類型。這不僅包括 React 函數和類別元件,還包括 HTML 元素的字串標籤(例如「div」、「span」)。當您想要接受元件作為 prop 並渲染它時, React.ElementType
特別有用,允許動態元件使用。
const DynamicComponent: React.ElementType = 'div';
export const Container = () => (
<DynamicComponent className="container">Hello, world!</DynamicComponent>
);
在這裡, DynamicComponent
的類型為React.ElementType
,允許它動態分配給不同類型的元件或 HTML 元素。
React.FC
主要用於定義功能元件。從 React 18 開始,它不再那麼有用了。
React.ElementType
在接受各種可渲染實體方面提供了更大的靈活性。當您需要可以動態接受不同類型的 React 元件或 HTML 元素的東西時,請使用React.ElementType
React.ReactElement
是一個具有type
、 props
和key
屬性的物件,由React.createElement()
函數建立。與React.ReactNode
相比,它是一種更具體的類型,表示可以由 React 直接渲染的元素。
const elementContent: React.ReactElement = <div>Hello, React.ReactElement!</div>;
export const Container = () => <>{elementContent}</>;
React.ReactNode
是最具包容性的類型,代表任何可以由 React 渲染的東西。這包括原始類型(字串、數字、布林值)、 JSX.Element
、 React.ReactElement
、這些類型的陣列等等。這是道具的首選類型,可以接受各種內容,例如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}
</>
);
};
下面的維恩圖描述了React.ReactNode
和React.ReactElement
之間的關係:
JSX.Element
本質上是一個具有更廣泛定義的React.ReactElement
,允許各種程式庫以自己的方式實作 JSX。它是 TypeScript 內部使用的類型,用於表示 JSX 表達式的傳回類型。
const jsxElement: JSX.Element = <span>Hello, JSX.Element!</span>;
export const Container = () => <>{jsxElement}</>;
React.ReactNode
是最靈活、最具包容性的,適合像孩子一樣可以接受多樣化內容的打字props。
React.ReactElement
和JSX.Element
更具體, React.ReactElement
適用於 React 建立的元素,而JSX.Element
適用於使用 JSX 語法定義的元素。
React.ReactNode
或React.ReactElement
/ JSX.Element
。基本上,函陣列件可以理解為:type ReactFC<P = {}> = (props: P) => React.ReactNode;
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>
);
}
是相同的:
const MyComponent = ({ children }: { children: React.ReactNode }) => {
return <div>{children}</div>;
};
export const App = () => {
return (
<div>
{MyComponent({
children: (
<>
Rendering MyComponent by
<strong>Invoking Function Component</strong>
</>
),
})}
</div>
);
}
了解這些 React 類型和介面之間的差異可以讓開發人員做出更明智的決策,從而產生更乾淨、更易於維護的程式碼。無論您是定義元件、接受動態內容還是處理子元件,選擇正確的類型對於充分發揮 React 和 TypeScript 的潛力至關重要。
請期待我即將發表的文章,這些文章將更深入地探討利用這些類型的理解的模式。