继承React组件的正确方式



我知道我的问题有点偏颇,但我对Javascript和prototypes非常陌生,我读过它,但我真的不知道如何将这些技术应用于我的实际问题。所以举个例子会很有帮助。所以我有一个React组件,基本上看起来是这样的:

var Component1 = React.createClass({
getInitialState: function () {
        return ({
            searchable: true,
        })
    },
function1: function () {
        return ({
            somevalue
        })
    },
render: function () {
        var redText = {
            color: 'red'
        };
        var redBorder = {
            color: 'red',
            border: '1px solid red'
        };
        return (
                <form>
                    <div>
                        <a onClick={this.props.handleAddClick}>Something</a>
                    </div>
                    <div>
                        <label>Some label</label>
                        <input type="text"/>
                    </div>
               </form> ) 
});

我还有基本上完全相同的Component2,但在其render函数的return中有一个额外的<input/>

我还有Component3,它有相同的功能,但有不同的render()功能。

那么如何在这里应用继承并避免复制粘贴3次呢?我只是错过了一些实用的插图,所以我很感激。

第1版____________________________________________________所以我试着按照第一个答案实现Prototype继承,但React似乎没有看到这些函数:getInitialState()为null,渲染后初始状态为null。这种方法有什么问题?

我还试着按照课本去做:

function MyPrototype() {};
MyPrototype.prototype.getInitialState = function () {
    return ({
        someProperty: true;
    })
};
function Component1() {};
Component1.prototype = Object.create(MyPrototype.prototype);
Component1.prototype.render = function () {
    console.log(this);
    return (<div></div>)};
var MyComponent1 = React.createClass(new Component1());

但当我打开浏览器时,我收到一个错误:Uncaught Invariant Violation: createClass(...): Class specification must implement a渲染method.

我这样做错了什么?

第2版_______________________________________________

实际上,我看到React不支持mixin,也不支持原型。应该使用合成。本文对此进行了解释:Dan Abramov的文章Mixins Are Dead。长寿命合成

在React中,组件的继承是强烈反对的
React更适合通过合成来表达相同的关系。

以下是使用合成的示例:

class Button extends Component {
  render() {
    return (
      <div className='Button' style={{ color: this.props.color }}>
        {this.props.children}
      </div>
    )
  }
}
class DeleteButton extends Component {
  render() {
    return (
      <Button color='red'>Delete</Button>
    )
  }
}

注意DeleteButton是如何使用Button的外观而不从中继承的。相反,Button通过props定义其可配置部分,DeleteButton提供这些道具。在实际的DOM中,<Button /><DeleteButton />都将呈现为单个DOM节点——递归解析发生在render()时,这是React的核心思想。

事实上,如果您不需要生命周期挂钩或本地状态,您甚至可以将组件定义为函数:

function Button({ color, children }) {
  return (
    <div className='Button' style={{ color }}>
      {children}
    </div>
  )
}
function DeleteButton() {
  return (
    <Button color='red'>Delete</Button>
  )
}

您甚至可以将类与函数混合使用。这在继承的情况下是不可能的,但在组合的情况下效果很好。

至于您的具体用例:

我还有基本上完全相同的Component2,但在其渲染函数的返回中有一个额外的<input/>

您可以让Component1接受this.props.children并在render()方法的返回值中使用它们,并让Component2渲染为<Component1><input /></Component>。这与我上面展示的非常相似。您也不必使用children道具——您可以在任何道具中传递React元素,例如<Component1 footer={<input />} />,然后您可以在Component1中使用this.props.footer

我还有Component3,它共享相同的函数,但有不同的render()函数。

如果它们共享任何其他代码(例如,计算某些数据的实用程序),请将组件外部的代码移动到共享模块中,然后从两个组件导入。

如果它们共享任何UI,请将其提取到另一个组件中,并从两个组件中使用它。

最新更新