React / TypeScript:扩展具有其他属性的组件

时间:2016-08-24 12:42:44

标签: reactjs typescript

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

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无关的道具。我怎样才能做到这一点 ?

6 个答案:

答案 0 :(得分:34)

您需要使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
    }
}

答案 1 :(得分:2)

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

$("#text").text(myHtml);

答案 2 :(得分:1)

根据经验,最好避免继承。幸运的是,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>
    }
}

答案 3 :(得分:1)

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

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 })
        }
    }
}

答案 4 :(得分:0)

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

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>
        );
    }
}

答案 5 :(得分:-2)

请记住,您正在执行的操作是反模式。 React建议在继承上使用合成。

“在Facebook上,我们在成千上万个组件中使用React,但尚未找到建议创建组件继承层次结构的用例。”

更多信息:https://reactjs.org/docs/composition-vs-inheritance.html