typescript 样式化构件默认属性

vd2z7a6w  于 2022-12-24  发布在  TypeScript
关注(0)|答案(5)|浏览(155)

如果下面的按钮带有defaultProp

export interface IButton {
  variant: 'action' | 'secondary';
}

export const Button = styled('button')<IButton>`
  background-color: #fff;

  ${props =>
    props.variant === 'action' &&
    css`
      color: blue;
    `};

  ${props =>
    props.variant === 'secondary' &&
    css`
      color: gray;
    `};
`;

Button.defaultProps = {
  variant: 'action',
};

有办法输入吗?当尝试使用它时

<Button>Hello</Button>

Typescript抱怨没有传递变量,有没有办法用样式化的组件输入defaultProps?

mcdcgff0

mcdcgff01#

问题是TypeScript 3.0在检查JSX元素时对defaultProps的支持需要在组件上声明defaultProps的类型。改变现有组件的defaultProps是行不通的,而且我不知道有什么好的方法可以在由styled这样的函数生成的组件上声明defaultProps。(在某种程度上,这是有意义的:这个库创建了一个组件,并不期望你修改它。也许这个库甚至会为了内部的目的而设置defaultProps。)kingdaro的解决方案很好,或者你可以使用一个 Package 器组件:

const Button1 = styled('button')<IButton>`
  background-color: #fff;

  ${props =>
    props.variant === 'action' &&
    css`
      color: blue;
    `};

  ${props =>
    props.variant === 'secondary' &&
    css`
      color: gray;
    `};
`;

export class Button extends React.Component<IButton> {
  static defaultProps = {
    variant: 'action'
  };
  render() {
    return <Button1 {...this.props}/>;
  }
}
57hvy0tb

57hvy0tb2#

你可以通过解构你的 prop 来实现你想要的。
看起来你仍然需要让你的组件知道它的 prop 类型。为此,只需要传递所有的 prop 而不去结构化它们(见下面的背景色)。

import styled from "styled-components";

interface IProps {
  variant?: 'action' | 'secondary';
}

export const Button = styled.div`
  ${(props: IProps) => `background-color: #fff;`}
  ${({ variant = 'action' }) => variant === 'action' ? `color: blue;` : `color: gray;`}
`;
u0sqgete

u0sqgete3#

据我所知,这还不太可能,而且不幸的是TS 3.0中增加的defaultProps支持没有涵盖这一点(这只适用于普通的组件类,以及 * 我认为 * 功能性组件)。如果我在这一点上错了,其他人可以随时纠正我。
不过,还有其他的写作方法,我通常是这样写的:

export interface IButton {
  variant?: 'action' | 'secondary';
}

const variantStyles = {
  action: css`
    color: blue;
  `,
  secondary: css`
    color: gray;
  `,
};

export const Button = styled('button')<IButton>`
  background-color: #fff;
  ${props => variantStyles[props.variant || 'action']};
`;
7kqas0il

7kqas0il4#

大多数情况下,我使用带有默认值的 Package 器组件:

interface IProps {
    // not optional
    variant: 'action' | 'secondary';
}

const SButton = styled.button<IProps>`
    ...styles
`

// make optional
export const Divider = (props: Partial<IProps>) => {
    // set default value
    const { variant = 'action', ...rest } = props;

    // insert default value
    return <SButton variant={variant} {...rest}>{children}</SButton>;
};

最好把造型 prop 和主要构件 prop 分开

interface IProps extends Partial<IStyledProps> {
    // component props
}

// or if you have composed component with multiple styled components
interface IProps extends Partial<IStyledProps1>, Partial<IStyledProps2>, Partial<IStyledProps3> {
    // component props
}
hgc7kmma

hgc7kmma5#

截至2022年12月,原始问题中的示例代码对我来说在React中使用样式化组件是有效的。
我在寻找一种方法来指定一个默认的StyleComponents主题时发现了这个问题。下面是我是如何做到的:

interface ITheme {
  color: string;
}

const defaultTheme: ITheme = {
  color: 'blue';
}

interface IButton {
  theme?: Theme;
}

export const Button = styled('button')<IButton>`
  color: ${({ theme }) => theme.color};
`;

Prose.defaultProps = {
  theme: defaultTheme,
};

使用上面的示例,我可以使用带有或不带有StyledComponents ThemeProvider的按钮。
对于ThemeProvider

<ThemeProvider theme={{ color: 'red' }}>
  <Button>I am a red button</Button>
</ThemeProvider>

没有ThemeProvider

<Button>I am a blue button</Button>

在Advanced文档的“Theming”代码示例中有一个这样的示例(虽然不是在TypeScript中):https://styled-components.com/docs/advanced#theming
另外--除非该示例被设计为使用defaultProps--有一种更简单的方法可以在不使用defaultProps的情况下在问题示例中使用默认颜色:

export interface IButton {
  variant: 'action' | 'secondary';
}

export const Button = styled('button')<IButton>`
  background-color: #fff;
  color: ${({ variant }) => (variant === 'secondary') ? 'gray' : 'blue' };
`;

相关问题