我有一个React按钮容器组件,根据用户使用的prop提供的类型,返回一个常规按钮、图标按钮或仅图标按钮。以下是ButtonContainer组件与Props的相关类型定义:
type ButtonWrapperProp = {
label?:string;
icon?:React.ReactNode;
onClick:()=>void;
type:'text'|'icon'|'iconOnly';
}
export const ButtonContainer = (props: ButtonWrapperProps) => {
const {
type = 'text',
onClick,
icon = <></>,
label = '',
} = props;
const rendorButton = () => {
switch (type) {
case 'text':
return (
<Button onClick={onClick}>{label} <Button/>
);
case 'iconOnly':
return (
<IconButton onClick={onClick}>
{icon}
</IconButton>
);
case 'icon':
return (
<Button startIcon={icon}>
{label}
</Button>
);
default:
return (
<Button onClick={onClick}>{label} <Button/>
);
}
};
return <>{rendorButton()}</>;
};
以下是我如何使用ButtonContainer组件:
<ButtonContainer type="iconOnly" onClick={onClick} icon={<DeleteIcon />}/>
<ButtonContainer type="text" onClick={onClick} label='Text button'/>
<ButtonContainer type="icon" onClick={onClick} label='Text and icon button' icon={<DeleteIcon />}/>
在上面的代码中,icon prop是可选的,因为它只用于带有图标的图标按钮和常规按钮。我希望只有当从ButtonContainer传递的类型为text时,icon prop才是可选的;如果传递给ButtonContainer的类型是icon或iconOnly,则它应该是一个必需的prop。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
我会选择使用辨别联合类型。
type属性作为一个辨别器,允许你将ButtonWrapperProps缩小到联合成员。
还要注意,我可以将每个联合成员的属性设为必需的,这样在使用时可以获得良好的体验 - 在设置了类型后,TS足够智能,能够提示哪些额外的属性是必需的。
type TextButtonProps = { type:'text' label:string; onClick:()=>void; } type IconOnlyButtonProps = { type:'iconOnly' icon:React.ReactNode; onClick:()=>void; } type IconButtonProps = { type:'icon' icon:React.ReactNode; label:string; onClick:()=>void; } type ButtonWrapperProps = TextButtonProps | IconOnlyButtonProps | IconButtonProps; export const ButtonContainer = (props: ButtonWrapperProps) => { const renderButton = () => { switch (props.type) { case 'text': return ( <Button onClick={props.onClick}>{props.label} </Button> ); case 'iconOnly': return ( <IconButton onClick={props.onClick}> {props.icon} </IconButton> ); case 'icon': return ( <Button startIcon={props.icon}> {props.label} </Button> ); } }; return <>{renderButton()}</>; };