如何使用样式组件扩展(MUI)React 组件的 TS 接口?

Posted

技术标签:

【中文标题】如何使用样式组件扩展(MUI)React 组件的 TS 接口?【英文标题】:How to extend TS interface for (MUI) React Component using styled-components? 【发布时间】: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 中抛出错误 【参考方案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

以上是关于如何使用样式组件扩展(MUI)React 组件的 TS 接口?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React MUI 覆盖 TextField 组件的宽度?

如何使用来自@mui/material 的样式使情感组件选择器在 nextjs 应用程序中工作?

如何向 React/MUI 自动完成组件添加唯一键?

如何在 React MUI <Menu /> 组件上制作方向 rtl?

一个mui扩展插件mui.showLoading加载框

TypeScript:为样式化的组件元素扩展 React 组件道具