reactjs - 如何在 TypeScript 中使用帶有 React 無狀態函數組件的 children
使用 TypeScript 與 React,我們不再需要擴展 React.Props,以便編譯器知道所有 React 組件的 props 都可以有 children:
interface MyProps { }
class MyComponent extends React.Component<MyProps, {}> {
public render(): JSX.Element {
return <div>{this.props.children}</div>;
}
}
然而,對於無狀態函數式組件似乎並非如此:
const MyStatelessComponent = (props: MyProps) => {
return (
<div>{props.children}</div>
);
};
產生編譯錯誤:
錯誤:(102, 17) TS2339: 屬性 'children' 在類型 'MyProps' 上不存在。
我猜這是因為編譯器真的無法知道一個純函數會在 props 參數中接收到 children。
所以問題是我們應該如何在 TypeScript 的無狀態函數組件中使用 children?
我可以回到舊的方式,MyProps 擴展 React.Props,但 Props 介面被標記為棄用,且無狀態元件據我了解既沒有也沒有支援 Props.ref。
所以我可以手動定義 children 屬性:
interface MyProps {
children?: React.ReactNode;
}
首先:ReactNode是正確的類型嗎?
第二:我必須將 children 寫成可選的(?),否則使用者會認為 children 應該是組件的一個 屬性(<MyStatelessComponent children={} />),如果沒有提供值就會報錯。
看起來我好像漏掉了什麼。有人能解釋一下我的最後一個例子是否是使用帶有 children 的無狀態函數型組件在 React 中使用的正確方式嗎?
答案#1
你可以對你的 props 使用 React.PropsWithChildren<P> 類型:
interface MyProps { }
function MyComponent(props: React.PropsWithChildren<MyProps>) {
return <div>{props.children}</div>;
}
答案#2
React 16.8 更新:自 React 16.8 起,React.SFC 與 React.StatelessComponent 名稱已不再被棄用。事實上,它們已成為 React.FunctionComponent 類型或簡稱 React.FC 的別名。
不過你會以相同的方式使用它們:
const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
<div>
<p>{props.propInMyProps}</p>
<p>{props.children}</p>
</div>
在 React 16.8 之前(舊版):
目前,你可以使用 React.StatelessComponent<> 類型,如下所示:
const MyStatelessComponent : React.StatelessComponent<{}> = props =>
<div>{props.children}</div>
我在那裡添加的是將組件的返回類型設置為 React.StatelessComponent 類型。
對於具有您自定義屬性(如 MyProps 介面)的組件:
const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
<div>
<p>{props.propInMyProps}</p>
<p>{props.children}</p>
</div>
現在,props 不僅擁有 MyProps 介面中的屬性,還有 children 屬性。
我在 TypeScript 版本 2.0.7 中檢查了這個
此外,你可以使用 React.SFC 來代替 React.StatelessComponent,以簡化寫法。
答案#3
更簡單的答案:使用 ReactNode:
interface MyProps {
children?: React.ReactNode
}
是否 children 是可選的(即是否有 ?)取決於你的元件。? 是表達這點最簡潔的方式,所以這樣做沒問題。
關於歷史:當最初被問到時,這不一定是正確答案:ReactNode 類型幾乎以目前的形式在 2017 年 3 月由這個拉取請求添加,但今天幾乎所有讀這篇文章的人都應該使用足夠現代的 React 版本。
最後,關於將 children 當作「屬性」傳遞(在 React 語境中,這應該是傳遞為「prop」而不是屬性):這是可行的,但在大多數情況下,傳遞 JSX children 會比較易讀:
<MyComponent>
<p>This is part of the children.</p>
</MyComponent>
比……更容易閱讀
<MyComponent children={<p>This is part of the children.</p>} />
