【问题标题】:How to extend TS interface for (MUI) React Component using styled-components?如何使用样式组件扩展(MUI)React 组件的 TS 接口?
【发布时间】:2021-09-19 06:19:42
【问题描述】:

我一直在试图弄清楚如何解决这个过载问题,但到目前为止还没有骰子。我正在使用 Typescript、Styled-components 和 material-ui。我正在使用 styled(MUIButton) 构建原生 MUI Button。通过 console.logs 我可以看到我的 props 传递到组件中,但是我不知道如何设置类型,所以重载错误消失了。

有什么想法吗?

相关文章:How to extend props for Material-UI components using Typescript?

错误:

代码:

import { default as MUIButton, ButtonProps } from '@material-ui/core/Button';
import styled, { css } from 'styled-components';
import { darken } from '@material-ui/core/styles';

interface IButton extends ButtonProps {
  format?: 'primary' | 'secondary';
  variant?: 'contained' | 'outlined' | 'text';
  label: string;
}

const Button = ({ format, variant, label }: IButton): JSX.Element => (
  <StyledButton format={format} variant={variant}>
    {label}
  </StyledButton>
);

Button.defaultProps = {
  format: 'primary',
  variant: 'contained',
};

export default Button;

const StyledButton = styled(MUIButton)<IButton>`
  //? contained variant (default)
  ${({ format, theme }) => `
  background-color: ${
    format === 'primary'
      ? theme.palette.colors.main
      : theme.palette.colors.secondary
  };
  color: ${theme.palette.font.secondary};
  font-weight: ${theme.agnosticStyles.font.weight.bold};
  padding: .7rem 4rem;
  &:hover {
    background-color: ${darken(theme.palette.colors.main, 0.2)};
  }
  `}
...
}

【问题讨论】:

  • 请提供包的版本
  • 它是一个新项目,所以它的所有最新版本
  • 它在 ts playground 中抛出错误

标签: reactjs typescript material-ui styled-components


【解决方案1】:

这是因为format 是一个自定义属性,您需要将其作为参数传递给StyleButton 元素。

由于您已经创建了IButton 接口,您可以像这样使用它:

const StyledButton = styled(MUIButton)<IButton>`
   ${props => console.log(props)}
   ...
`;

使用上面的代码,您还需要将界面中的label 设置为可为空(如果不这样做,您将收到错误Property 'label' is missing in type):

interface IButton extends ButtonProps {
  format?: "primary" | "secondary";
  variant?: "contained" | "outlined" | "text";
  label?: string;
}

const Button = ({ format, variant, label }: IButton): JSX.Element => (
  <StyledButton format={format} variant={variant}>
    {label}
  </StyledButton>
);

<Button label={"test"} format={"primary"} variant={"contained"} />

另一种方法是将您的 Button 设置为 FunctionComponnent,然后,您将不再需要 label 属性,您可以改用 children

interface IButton extends ButtonProps {
  format?: "primary" | "secondary";
  variant?: "contained" | "outlined" | "text";  
}

const StyledButton = styled(MUIButton)<IButton>`
   ...
`;

const Button: React.FC<IButton> = ({ format, variant, children }) => (
   <StyledButton format={format} variant={variant}>
      {children}
   </StyledButton>
);

<Button format={"secondary"} variant={"text"}>
   Test
</Button>

您可以在 styled-components here 中查看有关自定义道具的更多信息

更新

如果将&lt;StyledButton&gt;中的format替换为color,就会得到想要的按钮样式。

interface IButton extends ButtonProps {
  format?: "primary" | "secondary";
  variant?: "contained" | "outlined" | "text";  
}

const StyledButton = styled(MUIButton)<IButton>`
   ...
`;

const Button: React.FC<IButton> = ({ format, variant, children }) => (
   
   // ******
   // HERE'S THE TRICK -> INSTEAD FORMAT, YOU SHOULD SET COLOR
   // ******
   <StyledButton color={format} variant={variant}>
      {children}
   </StyledButton>
);

<Button variant={"contained"} format={"primary"}>
   primary
</Button>
<Button variant={"outlined"} format={"secondary"}>
   secondary
</Button>

【讨论】:

  • 嗨 Luis,感谢您的详尽回答。我更新了我的 styled-component 部分,使其具有 &lt;IButton&gt; 类型。但是,我正在构建的底层材料-ui &lt;Button&gt; 没有 format 属性。我很好奇如何将新的 format 属性附加到现有按钮以解决 TS 错误。
  • 当您说格式时,您是指样式颜色按钮吗?您只需将format 替换为color 即可完成此操作。我将在答案中包含一个示例。
  • 再次感谢您的反馈,在这种情况下,我实际上指的是向按钮添加一个名为“格式”的 new 属性。 format 有两个值:primary 或 secondary,它用于确定将在 styled-components 中实现的多种样式。 format 本身并不存在于 MUI 按钮上,因为我刚刚创建了它。最初帖子中的屏幕截图显示了唯一出现的错误,我相信这是打字稿说“嘿,按钮上不存在格式”。我不知道如何在按钮上输入以解决 TS 投诉
  • 我在最初的帖子中添加了更多内容,展示了“格式”属性的样式化组件意图以及它如何用于通过三元组应用样式(在本例中)。
  • 对不起,我好像在用 cmets 轰炸你。不过,我想我已经解决了。我应用了您的{children} 方法,错误都消失了。因此,在进一步探索了这个错误之后,我想我是在追逐一条红鲱鱼。该问题与我的label 有关,如果我将其设为条件并提供似乎也可以使用的默认值。 Property 'label' is missing in type '{ children: string; color?: "inherit" | "primary" | "secondary" | "default"; disabled?: boolean; disableElevation?: ... 是出现的错误。我不确定它为什么会出现。标签在IButton
【解决方案2】:

您的StyledButton 组件的外观并不完全清楚。来自@material-ui/core 的原始Button 不接受format 属性。这正是这个错误的原因。

如果您在 StyledButton 中以某种方式使用此属性,您应该相应地键入它:

const StyledButton = styled(MUIButton)<{format?: 'primary' | 'secondary'}>``;

尽管您可能正在寻找 color 属性,原始 Button 接受并且可能同时接受 primarysecondary 值。

【讨论】:

  • 没错,它没有format 属性。我基本上想将该属性附加到已经存在的材料 ui Button
猜你喜欢
  • 2020-12-27
  • 2019-03-28
  • 2020-08-20
  • 1970-01-01
  • 2018-12-24
  • 2018-10-05
  • 2016-06-11
  • 1970-01-01
  • 2020-05-02
相关资源
最近更新 更多