簡體   English   中英

通過React.cloneElement維護組件引用

[英]Maintaining Component Refs Through React.cloneElement

我一直在測試使用的可能的限制/危險React.cloneElement()來擴展組件的children 我發現的一種可能的危險是可能會覆蓋refkey類的道具。

但是,根據React的0.13版本候選對象 (早在2015年):

但是,與JSX和cloneWithProps不同,它還保留引用。 這意味着,如果您得到一個帶有裁判的孩子,則不會意外地從祖先那里偷走它。 您將獲得與新元素相同的引用。

[...]

注意: React.cloneElement(child, { ref: 'newRef' })確實會覆蓋ref,因此,除非您使用callback-refs,否則兩個父對象仍然不可能對同一個孩子擁有ref。

我編寫了一個小的React應用程序 ,該應用程序克隆了推入的子組件,並在兩個級別上測試ref的有效性:

class ChildComponent extends React.Component{
  constructor(props){
    super(props);   

    this.onClick = this.onClick.bind(this);
    this.extendsChildren = this.extendChildren(this);
  }

  onClick(e) {
    e.preventDefault();

    try{
      alert(this._input.value);
    }catch(e){
      alert('ref broken :(');
    }
  }

  extendChildren(){
    return React.Children.map(this.props.children, child => {
      return React.cloneElement(
        child,
        {
          ref: ref => this._input = ref
        }
      );
    });
  }

  render() {
    return(
      <div>
      <button onClick={this.onClick}>
        ChildComponent ref check
      </button>
      {this.extendChildren()}
    </div>
    );
  }
}


class AncestorComponent extends React.Component{
  constructor(props){
    super(props);

    this.onClick = this.onClick.bind(this);
  }

  onClick(e) {
    e.preventDefault();

    try{
      alert(this._input.value);
    }catch(e){
      alert('ref broken :(');
    }

  }

  render() {
    return (
    <div>
        <p>
          The expected behaviour is that I should be able to click on both Application and ChildComponent check buttons and have a reference to the input (poping an alert with the input's value).
        </p>
      <button onClick={this.onClick}>
        Ancestor ref check
      </button>
      <ChildComponent>
        <input ref={ref => this._input = ref} defaultValue="Hello World"/>
      </ChildComponent>
    </div>
    );
  }
}

但是,ChildComponent內部的cloningElements會覆蓋輸入字段中的AncestorComponent的ref prop,我希望在那里保留該ref prop,以及我定義為React.cloneElement一部分的新ref

您可以通過運行CodePen進行測試。

我做錯什么了嗎,或者此功能此后被刪除了?

根據Dan Abramov的響應 ,即使使用回調覆蓋引用,仍將覆蓋引用。 您需要在回調聲明中調用當前引用:

return React.Children.map(this.props.children, child =>
  React.cloneElement(child, {
    ref(node) {
      // Keep your own reference
      this._input = node;
      // Call the original ref, if any
      const {ref} = child;
      if (typeof ref === 'function') {
        ref(node);
      }
    }
  )
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM