Styled Components 渲染 Styled tag 基于 props
Styled Components rendering Styled tag based on props
我正在构建一个应用程序并想要有主要、次要和第三按钮,我不想创建 3 个单独的组件,它们是相同的但具有不同的样式组件,所以我想有条件地显示正确的标签,例如在下面的代码中,但我收到错误 JSX 元素类型 'ButtonStyles' 没有任何构造或调用签名。我究竟做错了什么?谢谢
import React from "react";
import styled from "styled-components";
const PrimaryStyles = styled.button`
width: 26rem;
height: 5rem;
background-image: ${({ theme }) => theme.gradients.ry};
border: none;
border-radius: 4px;
color: ${({ theme }) => theme.black};
font-size: 2rem;
box-shadow: 3px 3px 30px ${({ theme }) => theme.red + "70"};
cursor: pointer;
padding: 0 1rem;
`;
const SecondaryStyles = styled.button``;
const TertiaryStyles = styled.button`
border: none;
background: none;
color: ${({ theme }) => theme.grey};
`;
interface IProps {
type: "button" | "reset" | "submit";
children: React.ReactNode;
onClick: React.MouseEventHandler<HTMLButtonElement>;
primary?: boolean;
secondary?: boolean;
tertiary?: boolean;
}
export const Button: React.FC<IProps> = ({
children,
onClick,
type,
primary = true,
secondary,
tertiary,
}) => {
const ButtonStyles = primary
? PrimaryStyles
: secondary
? SecondaryStyles
: tertiary
? TertiaryStyles
: null;
return (
<ButtonStyles type={type} onClick={onClick}>
{children}
</ButtonStyles>
);
};
那是因为这个逻辑:
const ButtonStyles = primary
? PrimaryStyles
: secondary
? SecondaryStyles
: tertiary
? TertiaryStyles
: null;
如果不是 primary
、secondary
或 tertiary
,它将是 null
。所以你的代码会将 ButtonStyles
设置为 NULL
然后你不能这样做:
return (
<ButtonStyles type={type} onClick={onClick}>
{children}
</ButtonStyles>
);
解决此问题的方法是删除 NULL
选项,例如:
const ButtonStyles = primary
? PrimaryStyles
: secondary
? SecondaryStyles
: TertiaryStyles;
另一种避免三元条件运算符的方法是这样做的:
- 创建包含 3 种样式选项的对象:
interface IButtonStyles {
[key: string]: StyledComponent<"button", any, {}, never>;
}
const buttonStyleTypes: IButtonStyles = {
primary: PrimaryStyles,
secondary: SecondaryStyles,
tertiary: TertiaryStyles,
};
- 将您的 IProps 更改为类似的东西:
interface IProps {
type: "button" | "reset" | "submit";
children: React.ReactNode;
onClick: React.MouseEventHandler<HTMLButtonElement>;
styleType?: string;
}
- 此按钮组件:
const Button: React.FC<IProps> = ({
children,
type,
styleType = "primary",
}) => {
const ButtonStyles = buttonStyleTypes[styleType];
return <ButtonStyles type={type}>{children}</ButtonStyles>;
};
- 最后,您可以像这样创建按钮:
<Button type={"button"}>primary</Button>
<Button type={"button"} styleType='secondary'>secondary</Button>
<Button type={"button"} styleType='tertiary'>tertiary</Button>
我正在构建一个应用程序并想要有主要、次要和第三按钮,我不想创建 3 个单独的组件,它们是相同的但具有不同的样式组件,所以我想有条件地显示正确的标签,例如在下面的代码中,但我收到错误 JSX 元素类型 'ButtonStyles' 没有任何构造或调用签名。我究竟做错了什么?谢谢
import React from "react";
import styled from "styled-components";
const PrimaryStyles = styled.button`
width: 26rem;
height: 5rem;
background-image: ${({ theme }) => theme.gradients.ry};
border: none;
border-radius: 4px;
color: ${({ theme }) => theme.black};
font-size: 2rem;
box-shadow: 3px 3px 30px ${({ theme }) => theme.red + "70"};
cursor: pointer;
padding: 0 1rem;
`;
const SecondaryStyles = styled.button``;
const TertiaryStyles = styled.button`
border: none;
background: none;
color: ${({ theme }) => theme.grey};
`;
interface IProps {
type: "button" | "reset" | "submit";
children: React.ReactNode;
onClick: React.MouseEventHandler<HTMLButtonElement>;
primary?: boolean;
secondary?: boolean;
tertiary?: boolean;
}
export const Button: React.FC<IProps> = ({
children,
onClick,
type,
primary = true,
secondary,
tertiary,
}) => {
const ButtonStyles = primary
? PrimaryStyles
: secondary
? SecondaryStyles
: tertiary
? TertiaryStyles
: null;
return (
<ButtonStyles type={type} onClick={onClick}>
{children}
</ButtonStyles>
);
};
那是因为这个逻辑:
const ButtonStyles = primary
? PrimaryStyles
: secondary
? SecondaryStyles
: tertiary
? TertiaryStyles
: null;
如果不是 primary
、secondary
或 tertiary
,它将是 null
。所以你的代码会将 ButtonStyles
设置为 NULL
然后你不能这样做:
return (
<ButtonStyles type={type} onClick={onClick}>
{children}
</ButtonStyles>
);
解决此问题的方法是删除 NULL
选项,例如:
const ButtonStyles = primary
? PrimaryStyles
: secondary
? SecondaryStyles
: TertiaryStyles;
另一种避免三元条件运算符的方法是这样做的:
- 创建包含 3 种样式选项的对象:
interface IButtonStyles {
[key: string]: StyledComponent<"button", any, {}, never>;
}
const buttonStyleTypes: IButtonStyles = {
primary: PrimaryStyles,
secondary: SecondaryStyles,
tertiary: TertiaryStyles,
};
- 将您的 IProps 更改为类似的东西:
interface IProps {
type: "button" | "reset" | "submit";
children: React.ReactNode;
onClick: React.MouseEventHandler<HTMLButtonElement>;
styleType?: string;
}
- 此按钮组件:
const Button: React.FC<IProps> = ({
children,
type,
styleType = "primary",
}) => {
const ButtonStyles = buttonStyleTypes[styleType];
return <ButtonStyles type={type}>{children}</ButtonStyles>;
};
- 最后,您可以像这样创建按钮:
<Button type={"button"}>primary</Button>
<Button type={"button"} styleType='secondary'>secondary</Button>
<Button type={"button"} styleType='tertiary'>tertiary</Button>