【问题标题】:Modify render function of external React component (with no access)修改外部 React 组件的渲染功能(无权限)
【发布时间】:2018-10-31 15:41:17
【问题描述】:

我必须使用我无法修改的反应组件。由于更改,它来自外部来源。这也可能是我导入的 npm 包中的一个组件。这就是它的样子,一个简单的按钮:

class Button extends React.Component {

 // ... more code above  
 render() {
  const { onClick, disabled, children} = this.props;

  return (
    <button className={this.getClasses()} onClick={onClick} disabled={disabled}>
      {this.props.symbol && <Icon symbol={this.props.symbol} />}
      {children}
    </button>
  );

 }

}

如何在无法访问文件的情况下添加一些功能(我可以创建自己的组件来扩展按钮)?例如,我想要一个type 道具。我想我可以创建一个&lt;ButtonExtend onClick={resetState} type="button /&gt;

我该怎么做?理想情况下,我想让它更加灵活,所以我也可以这样做:&lt;ButtonExtend onClick={resetState} type="submit" name="extended button" /&gt;

我希望 html 使用我的附加 html 属性呈现来自 &lt;Button&gt; 的所有属性。所以我想使用原始的功能和我的附加道具。或者,如果组件无法更改另一个组件的渲染方法,这甚至是不可能的?

【问题讨论】:

  • 只需从Button 扩展您自己的类/组件并覆盖其render 方法
  • 你不能将属性注入到按钮 html 元素中,即使是装饰组件也是如此。不过,如果原始组件中仍有一些可重用的代码,您可以对其进行子类化并覆盖渲染方法。
  • @hindmost 以组合的方式不可能吗?
  • @abidibo 你有例子吗?不知道我是否可以关注
  • 当然可以,就像ButtonReact.Component扩展而来的一样

标签: javascript reactjs composition


【解决方案1】:

尽管refs (https://reactjs.org/docs/refs-and-the-dom.html) 可以访问组件的公共方法和属性,但您正在寻找的模式是高阶组件(HOC,https://reactjs.org/docs/higher-order-components.html

【讨论】:

  • 我找不到像我需要的那样修改渲染方法的 HOC 示例。你有例子吗?
  • 你需要什么道具,你期望什么渲染?
  • 例如,我想要一个类型道具。所以我可以说 type=„button“ 或 type=„submit“。我希望呈现一个简单的按钮。
【解决方案2】:

除非组件是为定制而设计的,否则没有直接的方法可以做到这一点。

Button 是一个设计糟糕的组件示例,因为它不接受额外的道具。可以将问题和 PR 提交到存储库以解决原始问题。

在扩展组件中,这可以通过从扩展组件传递道具来解决。

render结果可以修改:

class ButtonExtend extends Button {
 // ... more code above  
 render() {
  const button = super.render();
  const { symbol, children, ...props } = this.props;

  return React.cloneElement(button, {
    children: [
      symbol && <Icon symbol={symbol} />,
      ...children
    ],
    ...props
  });
}

如果需要修改的元素是嵌套的,这可能会变得混乱并导致创建不必要的元素。

更简洁的方法是将render粘贴到扩展组件中并修改它:

class ButtonExtend extends Button {
 // ... more code above  
 render() {
  const { symbol, children, ...props } = this.props;

  return (
    <button className={this.getClasses()} {...props}/>
      {symbol && <Icon symbol={symbol} />}
      {children}
    </button>
  )
 }
}

这样就可以当做

<ButtonExtend onClick={resetState} type="submit" name="extended button" />

【讨论】:

  • 如果组件是外部的(来自 NPM 包,IE)并且不需要特定的道具,则克隆元素和合并道具可能没有用。
  • “未预期”是什么意思? onClick 等是预期的。这将导致带有所需道具的重新渲染按钮。自己试试吧。
  • 他正在尝试获得不同的渲染,所以事件和标准道具可能还不够
  • 我投了反对票,因为 React 开发人员提倡组合而不是继承,并且您的解决方案涉及继承,即使 React 有这样的管理案例的模式。 “在 Facebook,我们在数以千计的组件中使用 React,我们还没有发现任何建议创建组件继承层次结构的用例。”参考:reactjs.org/docs/composition-vs-inheritance.html
  • @MosèRaguzzini 我非常了解组合而不是继承。 React 在合理的地方提倡组合,而不是作为一种应该盲目遵循的教条。覆盖render 结果是仅靠组合无法有效解决的极端情况。您显然没有尝试自己的答案。尝试按照您的建议使用 HOC 执行此操作,看看会发生什么。你最终会以任何方式扩展一个类,并以任何方式从 HOC 调用组件的 render 方法,如here 所示,以增强它(参见问题代码中的super.render() 部分)。
猜你喜欢
  • 2020-08-15
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 2021-11-26
  • 2018-03-24
  • 1970-01-01
相关资源
最近更新 更多