高阶组件和访问包装元素的子元素

Higher-Order Component and accessing child of the wrapped element

本文关键字:元素 包装 访问 组件 高阶      更新时间:2023-09-26

React 来说很新,我遇到了这个问题,我的 2 个组件非常相似,但差异大到不一样。

我找到了一种方法来组合组件并避免重复,随着Mixins的出现,我遇到了 HOC,我认为它可能非常强大,但对于像我这样还不熟悉 React 及其内部工作原理的人来说,这让我感到困惑。

所以我有我的主要组件(包装),然后将被包装。反过来,该组件呈现一个子组件(在我的例子中是其中一个包装组件的textarea,另一个是input字段)。

我想使用 HOC 的原因之一是我将事件侦听器绑定到文本输入,因此需要能够从 HOC 访问它。

    Textarea ---- InputController ---- InputHOC
    Input    ---/

在实践中,我已经设法使用ref中的回调将 DOM 元素传达回 HOC 的方法。但我觉得它很脏,因为我必须有 2 个回调:

InputController

 return (
  <div>
    {textareaHint}
    <div className='longtext-input-wrapper'>
      {textareaComponent}
    </div>
  </div>
)

textareaComponent

return <TextareaAutosize
          ref = {
            (c) => {
              this._input = c
            }
          }
          className={classList}
          minRows={MIN_ROWS}
        />

然后在InputHOC

 <div className={submitButtonClass}>
    <Button clickHandler={_buttonClickHandler.bind(this)} ref='submitButton'>
      <span className='button-text'>Ok</span>
      <span className='button-icon'>✔</span>
    </Button>
    <InputComponent ref={
        (item) => {
          if (item && !this.input) {
            this.input = item._input
          }
        }
      } 
    />
 </div>

然后我可以在componentDidMount中访问this.input

const inputNode = ReactDOM.findDOMNode(this.input)

它确实感觉很黑客,所以我想知道是否有更好的方法来解决这个问题?

非常感谢您的意见

@Jordan是对的,这不是使用HOC模式。 可以在此处找到此模式的一个很好的例子:https://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775。 您可以将 HOC 视为它包装的组件的超类,但它实际上不是一个类。 HOC 是一个函数,它接受一个反应组件并返回一个具有所需增强功能的新组件。

您正在做的是使用 ref 回调将所有组件链接在一起,并使其他组件知道其直接子组件以外的其他内容,这绝对不建议使用。 就您而言,我不明白为什么您不应该将InputHOC的所有内容都放入InputController. 然后,在InputController中定义要绑定到TextareaAutosize输入的函数,并将它们作为 props 传递。 它看起来像这样:

输入控制器:

class InputController extends React.Component {
  handleChange() {
    // Note that 'this' will not be set to the InputController element
    // unless you bind it manually
    doSomething();
  }
  render() {
    return (
      <Button clickHandler={_buttonClickHandler.bind(this)} ref='submitButton'>
        <span className='button-text'>Ok</span>
        <span className='button-icon'>✔</span>
      </Button>
      <div>
        {textareaHint}
        <div className='longtext-input-wrapper'>
          <TextareaAutosize callback={this.handleChange} />
        </div>
      </div>
    );
  }
}

文本区域自动调整大小

class TextAreaAutosize extends React.Component {
  render() {
    return (
      <textarea onChange={this.props.onChange}>
        Some text value
      </textarea>
    )
  }
}