【问题标题】:How to extend props for Material-UI components using Typescript?如何使用 Typescript 扩展 Material-UI 组件的道具?
【发布时间】:2018-02-19 12:33:16
【问题描述】:

我想使用 typescript 从 Material-UI 扩展 Button 组件的道具,以便能够将其他道具传递给它的孩子。

import { NavLink } from 'react-router-dom';
import { Button } from 'material-ui';

<Button
  component={NavLink}

  // NavLink props that needs to be added to typescript declarations
  activeClassName={classes.activeButton}
  exact={true}
  to={to}
>
  {title}
</Button>

我尝试在 ./app/types/material_ui.d.ts 中添加以下声明:

declare module 'material-ui' {
  interface Button {
    activeClassName?: any;
    exact?: boolean;
    to?: string;
  }
}

这会引发错误“TS2693:'Button' 仅指一种类型,但在此处用作值。”。

我也尝试过声明:

import * as React from 'react';

import { PropTypes, StyledComponent } from 'material-ui';
import { ButtonBaseProps } from 'material-ui/ButtonBase';

declare module 'material-ui' {
  export interface ButtonProps extends ButtonBaseProps {
    color?: PropTypes.Color | 'contrast';
    component?: React.ReactNode;
    dense?: boolean;
    disabled?: boolean;
    disableFocusRipple?: boolean;
    disableRipple?: boolean;
    fab?: boolean;
    href?: string;
    raised?: boolean;
    type?: string;

    activeClassName?: any;
    exact?: boolean;
    to?: string;
  }

  export class Button extends StyledComponent<ButtonProps> { }
}

这会引发错误“TS2323:无法重新声明导出的变量 'Button'”。

我的 tsconfig.json 看起来像这样:

{
  "compilerOptions": {
    ...
    "paths": {      
      "history": ["./node_modules/@types/history/index"],
      "redux": ["./node_modules/@types/redux/index"],
      "react": ["./node_modules/@types/react/index"],
      "*": ["./app/types/*", "*"]
    },
  },
  ...
}

最后是来自 Material-UI 的原始类型定义:

import * as React from 'react';
import { StyledComponent, PropTypes } from '..';
import { ButtonBaseProps } from '../ButtonBase';

export interface ButtonProps extends ButtonBaseProps {
  color?: PropTypes.Color | 'contrast';
  component?: React.ReactNode;
  dense?: boolean;
  disabled?: boolean;
  disableFocusRipple?: boolean;
  disableRipple?: boolean;
  fab?: boolean;
  href?: string;
  raised?: boolean;
  type?: string;
}

export default class Button extends StyledComponent<ButtonProps> {}

我正在使用 material-ui 1.0.0-beta.8 和 react 15.6.1、react-router-dom 4.2.2 和 typescript 2.5.2。

【问题讨论】:

    标签: reactjs typescript material-ui


    【解决方案1】:
    import React, { FC } from 'react';
    
    import { Button, ButtonProps } from '@material-ui/core';
    
    interface IProps extends ButtonProps {} // your custom props
    
    const ButtonHco: FC<IProps> = ({
      variant,
      color,
      children,
      size,
      disabled
    }) => {
      return (
        <Button variant={variant} color={color} size={size} disabled={disabled}>
          {children}
        </Button>
      );
    };
    
    export default ButtonHco;
    

    【讨论】:

    • 谢谢,它有效。有人知道在哪里可以找到和提取 Box 的“justifyContent”属性的默认值吗?
    【解决方案2】:

    以下代码对我有用

    import { Button, StyledComponent } from 'material-ui';
    import { ButtonProps } from 'material-ui/Button';
    
    declare module 'material-ui' {
      export interface MyProps {
    
        exact?: boolean;
        to?: string;
      }
      export class Button extends StyledComponent<ButtonProps & MyProps> {
      }
    
    }
    

    "TS2693: 'Button' only refers to a type, but is being used as a value here. 没有问题,我也在使用 Typescript 2.5.2

    【讨论】:

    • 看起来很简单,但对我来说这行不通。我收到以下错误:TS2323:无法重新声明导出的变量“Button”。 TS2484:导出声明​​与“Button”的导出声明冲突。这可能与 @987654321 有关@。有什么想法吗?
    • 有趣,这是另一个issue,你能创建一个最小的可重现回购吗?
    • @eitido 我知道已经两年了,但是对于其他来到这里的人来说,原因是 Button 是一个 MUI 组件,而您正在尝试创建自己的 Button 组件,所以这是一个命名冲突.您只需将 MUI 的按钮别名为 MuiButton(或其他名称)。
    • 它只是不起作用。它对其他人有用吗?
    【解决方案3】:

    这是一个扩展 Material UI 按钮的简约示例(未经测试)。 扩展字段将简单地附加在按钮标签之后。

    import * as React from 'react';
    import { ButtonProps } from '@material-ui/core/Button';
    import { Button } from '@material-ui/core';
    
    interface Props{
      extendedField: string;
    }
    
    export class MyExtendedButton extends React.Component<ButtonProps & Props>{
      render(){
    
        const {
          extendedField,
          children,
          ...buttonProps,
        } = this.props;
    
        return (<Button {...buttonProps}>
          {children}
          : <span style={{color: 'red'}}>
            {extendedField}
          </span>
        </Button>);
      }
    }
    

    【讨论】:

    • 非常有帮助,感谢分享基于类的示例 :)
    【解决方案4】:

    有点晚了,但这是另一种解决方案。另请参阅 MUI 文档 Usage of component prop 。 以下按钮使用 Link 组件。它还使用 Link 的特定道具及其类型。它还添加了自己的 sesific 道具。

    import React from 'react'
    import MuiButton, {ButtonProps} from '@material-ui/core/Button'
    
    interface ButtonOptions {
        // your custom options with their types
      }
    
    const Button = <C extends React.ElementType>(props: ButtonProps<C, {component?: C}> & ButtonOptions ) => {
      return <MuiButton {...props}>{props.children}</MuiButton>
    }
    
    export default Button
     
    // use like this:  
    import {Link} from 'react-router-dom'
    <Button component={Link} to={'/somelocation'}>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-10
      • 2020-07-22
      • 2021-01-26
      • 2020-06-30
      • 2020-07-20
      • 1970-01-01
      • 2019-07-15
      • 1970-01-01
      相关资源
      最近更新 更多