React / Typescript:合并属性的自定义组件的惯用代码?

时间:2017-10-12 04:07:18

标签: css twitter-bootstrap reactjs typescript

版本:Typescript 2.3,React 16,Bootstrap 4。

我有一个解决方案,下面概述了一些工作,包括导入另一个外部库来完成这项工作。我觉得必须有一个标准的解决方案来合并自定义组件的属性,但使用classnames包是我提出的唯一方法。

为我的应用编写自定义AppButton组件,我想要一个默认样式,但允许覆盖。

第一个版本看起来像:

export interface AppButtonProps 
extends ButtonHTMLAttributes<HTMLButtonElement>{
}
export class AppButton 
extends React.PureComponent<AppButtonProps, object> {
  render(){
    return <button 
      {...this.props}
      className="btn btn-primary" 
    />;
  }
}

与此类代码一起使用,以覆盖按钮的颜色:

<AppButton type="submit" className="btn-success">Do the thing</AppButton>

但这不起作用,取决于<button>属性的顺序,你要么得到一个btn btn-primarybtn-success的按钮 - 但我想要的是{{1} }。

我当前的方法使用classnames包:

btn btn-success

这只排序有效,它导致export class AppButton extends React.PureComponent<AppButtonProps, object> { render(){ return <button {...this.props} className={classNames("btn", "btn-primary", this.props.className)} />; } } ,这在合并属性方面不是我想要的,但它在这个特定情况下正确显示 - 我想因为Bootstrap更喜欢btn btn-primary btn-success而不是btn-success

我能看到的唯一明显的解决方案是获取我需要的确切样式,即解析并扫描btn-primary的传入props.style属性,如果不存在,则只添加btn-*。< / p>

所以,问题是:在一个Typecript,React或Bootstrap中是否有一个内置的实用程序可以解决这个问题?或者我想要一些其他的包裹?

或许这实际上是错误的方法,我应该在btn-primary编写自己的自定义属性并编写一堆样式逻辑?

1 个答案:

答案 0 :(得分:1)

如果没有提供其他值,我建议使用defaultPropsbtn-primary用作默认类:

export interface AppButtonProps 
extends ButtonHTMLAttributes<HTMLButtonElement>{
}
export class AppButton 
extends React.PureComponent<AppButtonProps, object> {
  static defaultProps = {
    className: "btn-primary",
  };
  render(){
    return <button 
      {...this.props}
      className={classNames("btn", this.props.className)} 
    />;
  }
}

根据您在下面的评论,您还可以为确定按钮主要外观的课程添加单独的道具:

export interface AppButtonProps 
extends ButtonHTMLAttributes<HTMLButtonElement>{
  mainButtonClass?: string;
}
export class AppButton 
extends React.PureComponent<AppButtonProps, object> {
  static defaultProps = {
    mainButtonClass: "btn-primary",
  };
  render(){
    return <button 
      {...this.props}
      className={classNames("btn", this.props.mainButtonClass, this.props.className)} 
    />;
  }
}