【问题标题】:React/TypeScript: extending a component with additional propertiesReact/TypeScript:使用附加属性扩展组件
【发布时间】:2016-08-24 12:42:43
【问题描述】:

我正在尝试使用 react 来重新创建我的当前组件(用纯打字稿编写),但我找不到一种方法来为扩展另一个组件的组件提供额外的道具。

export interface DataTableProps {
    columns: any[];
    data: any[];
}

export class DataTable extends React.Component<DataTableProps, {}> {
   render() {
       // -- I can use this.props.columns and this.props.data --
   }
}

export class AnimalTable extends DataTable {
    render() {
       // -- I would need to use a this.props.onClickFunction -- 
    }
}

我的问题是我需要给 AnimalTable 一些与 DataTable 无关的道具。我怎样才能做到这一点 ?

【问题讨论】:

标签: reactjs typescript


【解决方案1】:

您需要将DataTable 设为通用,以便您能够使用扩展DataTableProps 的接口:

export interface AnimalTableProps extends DataTableProps {
    onClickFunction: Function;
}

export class DataTable<T extends DataTableProps> extends React.Component<T, {}> { }

export class AnimalTable extends DataTable<AnimalTableProps> {
    render() {
        // this.props.onClickFunction should be available
    }
}

【讨论】:

  • 感谢@Nitzan Tomer!
  • 构造函数有问题,无法正常使用this.state TS2322:类型'{ ...properties of state }'不可分配给类型'Readonly'。
  • @meteor 如果没有看到您的代码,很难说出问题所在。尝试提出一个新问题并在那里发布您的相关代码。
  • 考虑使用abstract 类/函数。 (see answer below)
  • @meteor 你需要使用你指定的... export class DataTable extends React.Component{ constructor(t: T) { super(t) ;} } 希望这对其他人有所帮助。我将在下面发布一个完整的示例
【解决方案2】:

对于那些需要的人,基类可以声明所有实例必须实现的必需/​​抽象方法:

import { Component } from 'react'


abstract class TestComponent<P = {}, S = {}, SS = any> extends Component<P, S, SS> {
  abstract test(): string
}


type Props = {
  first: string,
  last: string,
}

type State = {
  fullName: string,
}

class MyTest extends TestComponent<Props, State> {
  constructor(props: Props) {
    super(props)
    this.state = {
      fullName: `${props.first} ${props.last}`
    }
  }

  test() {
    const { fullName } = this.state
    return fullName
  }
}

【讨论】:

    【解决方案3】:

    我发现的最优雅的解决方案(没有额外的泛型类)是

    interface IBaseProps {
        name: string;
    }
    
    class Base<P> extends React.Component<P & IBaseProps, {}>{
    
    }
    
    interface IChildProps extends IBaseProps {
        id: number;
    }
    
    class Child extends Base<IChildProps> {
        render(): JSX.Element {
            return (
                <div>
                    {this.props.id}
                    {this.props.name} 
                </div>
            );
        }
    }
    

    【讨论】:

      【解决方案4】:

      根据经验,最好避免继承。幸运的是 TS 和 react 是很好的工具(例如,与 c# 不同,继承通常会为您节省一堆样板文件)

      export interface DataTableProps {
          columns: any[];
          data: any[];
      }
      
      export class DataTable extends React.Component<DataTableProps, {}> {
         render() {
             // -- I can use this.props.columns and this.props.data --
         }
      }
      
      export type AnimalTableProps = DataTableProps & {
          onClickFunction: () => void;
      };
      
      export class AnimalTable extends React.Component<AnimalTableProps, {}> {
          render() {
              const {onClickFunction, ...tableProps} = this.props;
              // use onClickFunction however you need it
              return <DataTable {...tableProps}></DataTable>
          }
      }
      

      【讨论】:

        【解决方案5】:

        创建可以扩展和维护状态和道具的组件的完整示例

        import { Component } from "react";
        
        // Props for the Base Component
        export interface BaseComponentProps { }
        
        // State for the Base Component
        export interface BaseComponentState {
            isLoaded?: boolean
        }
        
        // The Base Component that your components can extend
        export class BaseComponent<Props extends BaseComponentProps, State extends BaseComponentState, SS = any> extends Component<Props, State, SS> {
        
            State: BaseComponentState = {
                isLoaded: false
            }
        
            constructor(props: Props) {
                super(props);
            }
        
            componentDidMount() {
                this.setState({ isLoaded: true })
            }
        }
        
        // Props for your specialized component
        export interface MainComponentProps extends BaseComponentProps {
        
        }
        
        // State for your specialized component
        export interface MainComponentState extends BaseComponentState {
            CanRead: boolean
        }
        
        // Your component which now extends the BaseComponent
        export class MainComponent extends BaseComponent<MainComponentProps, MainComponentState> {
            state: MainComponentState = {
                CanRead: false
            }
        
            componentDidMount() {
                super.componentDidMount();
        
                if (this.state.isLoaded) {
                    this.setState({ CanRead: true })
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-09-17
          • 2019-06-30
          • 2020-06-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多