我正在 TypeScript 中创建 React 组件,并键入提示属性,如下所示:
export interface ExampleProps {
someProp: string,
anotherProp: React.ReactNode
}
export default function Example({
someProp,
...props
}: ExampleProps) {
return (
<div {...props}>...</div>
);
}
我还想传递标准的 React/HTML 属性,如
className
、children
、style
、id
、title
、lang
等......而不必显式写出所有他们。所以我可以做类似的事情:
<Example className="some-class" someProp="value" anotherProp={<div></div>}>Content</Example>
我本以为应该可以为此扩展一个接口,例如:
export interface ExampleProps extends PropsWithChildren {
someProp: string,
anotherProp: React.ReactNode
}
但这抱怨:
Generic type 'PropsWithChildren' requires 1 type argument(s)
export interface ExampleProps extends PropsWithChildren<typeof Example> {
someProp: string,
anotherProp: React.ReactNode
}
但是这会抱怨,
Type { children: string; className: string; someProp: string, anotherProp: Element }' is not assignable to type 'IntrinsicAttributes & SlotsProps
然后我尝试了:
export interface ExampleProps extends PropsWithChildren<{}> {
someProp: string,
anotherProp: React.ReactNode
}
但这会抱怨,
Property 'className' does not exist on type 'IntrinsicAttributes & SlotsProps'
,因为显然 PropsWithChildren 包含的都是子元素。
所以我也尝试用
PropsWithChildren
和 ComponentProps
替换 ElementType
但这也没有帮助。
React 不维护适用于所有元素的标准 props 列表吗?
在我的代码中使用 juliomrc 的答案一年半后回到这个问题,我有一些新的见解想分享:
不要这样做!这不是一个好主意。
HTML 元素有很多 props。将它们添加到可重用组件中会损害可发现性。在您的组件上使用自动完成功能的人将不得不费力地浏览一百个从未被任何人使用过的通用道具,才能找到少数特定于您的组件的道具。
在实践中,您几乎总是只需要以下内容:
interface ElementProps {
id?: string;
children?: ReactNode;
className?: string;
style?: CSSProperties;
}
此外,您可能会遇到冲突的 prop 定义,尤其是事件处理程序。我个人更喜欢以下签名
onChange
:
onChange: (value: T, event: ChangeEvent) => any
这允许您只传递 setter 以获得反应状态。但这会与您从 HTMLAttributes 获得的冲突。
但是,即使您愿意使用 HTMLAttributes 事件处理程序,事件处理程序的目标也可能与您向其传递其余属性的元素不同。因此,您将把它从 HTMLAttributes 中排除并重新定义它。
我认为这是不值得的。最好暗示一下你实际使用的道具。
如果您确实希望能够将任意 props 传递给特定的 HTML 元素,您始终可以为此创建一个特定的 props:
interface ElementProps {
id?: string;
children?: ReactNode;
className?: string;
style?: CSSProperties;
containerProps?: HTMLAttributes<HTMLDivElement>,
}
export function Element({children, containerProps, ...props}: ElementProps) {
// ...
return (
<div {...{...props, ...containerProps}}>
{/* ... */}
{ children }
{/* ... */}
</div>
)
}
export function TypographyH1({
children,
...props
}: React.HTMLAttributes<HTMLHeadingElement>) {
将此方法用于特定元素类型 你可以将特定的元素类型更改为这个
<div/> = <HTMLDivElement>
<a/> = <HTMLAnchorElement>
<span /> = <HTMLSpanElement/>
<input /> = <HTMLInputElement/>