React高阶组件:添加实例方法的正确方法

时间:2019-03-29 13:36:51

标签: javascript reactjs higher-order-components

我正在尝试将实例方法添加到包装的组件中。我通过扩展包装组件的原型来做到这一点:

const useAppContext = () => WrappedComponent => {
    WrappedComponent.prototype.$context = { abc: 'abc' };
    return class extends React.Component {
        render() {
            return <WrappedComponent {...this.props} />;
        }
    };
};

@useAppContext()
class NavigationLinkList extends Component {
    render() {
        console.log('this.$context', this.$context);
    };
};

虽然这种可行,但我不确定是否有一种更干净的方法可以执行此操作,而这是“常规”的反应方式。我在文档中找不到任何内容,这种方式似乎有点像hack。还有其他(更清洁的)方法吗?

2 个答案:

答案 0 :(得分:1)

一种更为谨慎的方法是不修改类原型而是对其进行扩展:

const useAppContext = () => WrappedComponent => {
    return class extends WrappedComponent {
        $context = { abc: 'abc' };
    };
};

这只是一个装饰器,不是有效的高阶组件,因为它不能与功能组件一起使用。

React惯用的一种方法是使用组合而不是继承。扩展高级组件中现有组件功能的一种常用方法是通过props提供必要的功能,因为props是React中组件之间进行通信的主要方式:

可以是:

const useAppContext = () => WrappedComponent => props => {
    return <WrappedComponent $context={{ abc: 'abc' }} {...props} />;
};

@useAppContext()
class NavigationLinkList extends Component {
    render() {
        console.log(this.props.$context);
        ...
    };
};

答案 1 :(得分:0)

高阶组件通常向包装的组件道具添加功能,而不是其原型。

在原型中添加方法会使包装的组件耦合到装饰器(这意味着它在未装饰时将无法工作),并且将使其难以测试。

加上,提到了一个发情期,它不适用于功能组件。

您总是可以重写装饰器,以将上下文注入包装好的组件props中,例如:

const useAppContext = () => WrappedComponent => {
    WrappedComponent.prototype.$context = { abc: 'abc' };
    return class extends React.Component {
        render() {
            return <WrappedComponent {...this.props} context={{ adb: 'abc')} />;
        }
    };
};