reactjs - 如何為一個 React 組件設置類型,使其可以接收另一個組件作為 prop,以及該組件的所有 props?
我有一個 React 元件 <Wrapper>,我可以如下使用:
// Assuming Link is a component that takes a `to` prop: <Link to="/somewhere">label</Link>
<Wrapped as={Link} to="/somewhere">label</Wrapped>
如果沒有傳入 as 屬性,它將假設使用 <a>。但如果傳入一個組件到 as,那麼對該組件有效的所有屬性現在也應該是 Wrapped 的有效屬性。
有沒有辦法在 TypeScript 中輸入這個?我目前正在考慮以下方向:
type Props<El extends JSX.Element = React.ReactHTMLElement<HTMLAnchorElement>> = { as: El } & React.ComponentProps<El>;
const Wrapped: React.FC<Props> = (props) => /* ... */;
然而,我不確定 JSX.Element 和/或 React.ComponentProps 是否是這裡相關的類型,而且這無法編譯,因為 El 無法傳給 ComponentProps。那裡正確的類型應該是什麼,而且像這樣的做法是否可能?
答案#1
你需要的類型是 ComponentType 和 ElementType。
import React, { ComponentType, ElementType, ReactNode } from 'react';
type WrappedProps <P = {}> = {
as?: ComponentType<P> | ElementType
} & P
function Wrapped<P = {}>({ as: Component = 'a', ...props }: WrappedProps<P>) {
return (
<Component {...props} />
);
}
藉此,你可以做:
interface LinkProps {
to: string,
children: ReactNode,
}
function Link({ to, children }: LinkProps) {
return (
<a href={to}>{children}</a>
);
}
function App() {
return (
<div>
<Wrapped<LinkProps> as={Link} to="/foo">Something</Wrapped>
<Wrapped as="div" style={{ margin: 10 }} />
<Wrapped />
</div>
);
}
