【问题标题】:Props in inheritance and composition继承和组合中的道具
【发布时间】:2016-10-11 17:51:35
【问题描述】:

我有一个名为 Panel 的 React 类,我想将它用作 UI 中各种特定面板的可重用组件。每个面板都有一个共同的标题栏和一个“提交”按钮,但每种面板的主体都是独一无二的。

我可以使用继承(子类化)或组合来实现这一点,但在这种情况下哪种方式最好?

我尝试过子类化,在父级Panel 中有一个渲染方法,然后让子面板覆盖renderBody 方法,render 使用该方法。这似乎崩溃了,因为每个特定面板都需要自己的道具(例如“标题”),并且当修改的道具在组件构造函数中传递给 super 时,React 会抱怨(错误消息是,“当调用 super() . . . 确保传递与组件的构造函数相同的道具。”)。由于“标题”特定于某种面板,我不希望最终消费者必须自己指定“标题”道具。

class Panel extends React.Component {

  render() {
    return (
      <div>
        <div>{this.props.title}</div>
        <div>{this.renderBody()}</div>
        <div><button>Submit</button></div>
      </div>
    )
  }

}

class SomeSubPanel extends Panel {

  constructor(props) {
    // React throws the error message at the following line
    let newProps = Object.assign({}, props, {title: "Some Sub Panel"})
    super(newProps)
  }

  renderBody() {
    return (<div>Panel Body Goes Here</div>)
  }

}

使用组合似乎不像子类化那样整洁,因为每个面板只需要有一个特定的主体,但主体(即 HTML)不能在组件之间传递。

拥有可以将特征传递给可重用父组件的子组件的“反应方式”是什么?

非常感谢!

【问题讨论】:

  • 你能发布一些你的代码吗?您的子类的构造函数应该将 props 传递给 super,我不明白为什么仅从描述来看这会是一个问题。
  • 问题是那个错误信息。子类想通过添加“标题”来调整“道具”,但 React 不允许修改道具。我会尝试发布一些代码。
  • 我认为组合通常是优选的,特别是考虑到无状态反应组件(所有条件都相同)通常被认为是更可取的(对于优选的某些定义)。
  • 关于您的代码的快速说明:您不能在渲染中返回多个顶级元素。您需要将它们包装在父 div 中或返回它们的数组并给每个唯一键
  • 调整示例代码更正确。

标签: inheritance reactjs subclass composition subclassing


【解决方案1】:

我认为 React 的做法很简单:

// using a function for brevity, but could be a class
let Panel = ({ title, handleSubmit, children }) =>
  <div>
    <h1>{title}</h1>
    {children}
    <button onClick={handleSubmit}>Submit</button>
  </div>

然后在别处:

<Panel title="Foo" handleSubmit={onSubmit}>{specificChildContent}</Panel>

【讨论】:

    【解决方案2】:

    一定要使用组合。一般来说,我不认为你应该扩展你自己的 React 组件。以下是实现它的方法:

    class ReusablePanel extends React.Component {
      render () {
        return (
          <div>
            <div>{this.props.title}</div>
            <button onClick={this.props.onSubmit}>Submit</button>
            {this.props.children}
          </div>
        )
      }
    }
    
    class FootballPanel extends React.Component {
      handleSubmitButtonClick = () => {
        // do something
      }
    
      render () {
        return (
          <ReusablePanel title='Football' onSubmit={this.handleSubmitButtonClick}>
            <div>{/* Football markup */}</div>
          </ReusablePanel>
        )
      }
    }
    
    class ArsenalPanel extends React.Component {
      handleSubmitButtonClick = () => {
        // do something
      }
    
      render () {
        return (
          <ReusablePanel title='Arsenal' onSubmit={this.handleSubmitButtonClick}>
            <div>{/* Arsenal markup */}</div>
          </ReusablePanel>
        )
      }
    }
    

    【讨论】:

    • 为什么“你永远不应该扩展你自己的 React 组件”?
    • @MarioTacke 我不知道“从不”...但是扩展组件令人困惑,imo。按原样使用组件可以通过子类化实现您所做的一切,而无需遵循额外的噪音和继承树。
    • 对这个问题的两个答案都是正确的,但这是第一个并且遵循问题的给定类范式。谢谢大家!
    猜你喜欢
    • 2020-03-04
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多