在 React 中具有"变体"的组件 - 条件渲染



这里非常基本的问题。

我正在尝试开始学习 React,我对处理这种事情的最佳设计模式感到好奇。

我有一个按钮组件,我想要应用不同类的组件的"主要"和"次要"变体。 以下情况是最好的方法吗?我正在传递一个"变体"道具,用于定义要使用的按钮。

如果这不是最好的解决方案,如果我想要特定组件的"变体"会是什么。

谢谢!

class Button extends Component {
render() {
// --- SECONDARY BUTTON --- //
if(this.props.variant == 'secondary') {
return (
<div className = 'button-wrapper secondary'>
<div className = 'button'>
{this.props.text}
</div>
</div>
);
// --- PRIMARY BUTTON --- //
}else if(this.props.variant == 'primary') {
return (
<div className = 'button-wrapper primary'>
<div className = 'button'>
{this.props.text}
</div>
</div>
);
}
}
}

如果你的区别只在className,也许你可以通过以下方式实现同样的目标:

render() {
const { variant } = this.props;
return (
<div className = {`button-wrapper ${ variant === 'secondary' ? '' : 'primary' }`}>
<div className = 'button'>
{this.props.text}
</div>
</div>
);

我建议使用一些 npm 包来处理这类事情,因为它们会因组件而异,你最终会在组件中放置许多丑陋的 if-else 语句。你可以通过创建一个接受 props 并返回最终一组类的钩子来获得它,但这又是一个丑陋的钩子。

你应该尝试一下 npm pkg@vtechguys/vs.


import { GetVariantProps, vs } from "@vtechguys/vs";

export const button = vs({
// Example with Tailwind rich classes
base: ["font-semibold", "border", "rounded"],
variants: {
intent: {
color: [
"bg-blue-500",
"text-white",
"border-transparent",
"hover:bg-blue-600"
],
secondary: [
"bg-white",
"text-gray-800",
"border-gray-400",
"hover:bg-gray-100"
]
},
size: {
small: ["text-sm", "py-1", "px-2"],
medium: ["text-base", "py-2", "px-4"]
}
},
defaultVariants: {
intent: "primary",
size: "medium"
}
});

export type ButtonVariantProps = GetVariantProps<typeof button>;

不是可以简单地用作


import React from "react";

type ButtonOwnProps = {
// ... some button props ...
};

type ButtonProps = React.PropsWithChildren<ButtonVariantProps & ButtonOwnProps>;


export function ButtonTailwind(props: ButtonProps) {
const { color, size, children, ...rest } = props;
// you can event extract it in a hook to make it more clean
const variants = button({ color, size });
// Applicable Tailwind classes
const classes = clsx(variants);

return (
<button className={classes} {...rest}>
{children}
</button>
);
}

最新更新