在父母中调用函数并将“this”绑定到孩子身上?

时间:2017-10-28 16:19:43

标签: javascript reactjs ecmascript-6

我尝试做的是从子元素中调用父元素中定义的函数,但将this绑定到调用函数的子元素,而不是函数运行的父元素。“ p>

有没有办法做到这一点,如果是这样,这会是反模式吗?谢谢。

传递给孩子的家长功能

onSelect = (event => {
  // Some code where `this` is the scope of the child calling the function
  // Not the scope of the parent where the function is defined
}

家长渲染功能

render() {
  return (
    <Child onSelect={this.onSelect} />
   )
}

儿童渲染功能

render() {
  return (
    <button onClick={this.props.onSelect.bind(this)} />
  )
}

2 个答案:

答案 0 :(得分:2)

  

有没有办法做到这一点,如果是这样,这会是反模式吗?

  1. 传递函数(不是箭头函数),并将其绑定在构造函数中。

  2. 这是一种反模式,因为父母需要知道孩子的内心工作,这会打破封装。

  3. 你是如何做到的:

    使用标准方法,而不是箭头功能:

    onSelect(e) {  
      this.setState({
        selected: !!e.target.value
      });
    }
    

    在构造函数中绑定方法:

    constructor(props) {
      super(props);
    
      this.state = {
        selected: false
      };
    
      this.onSelect = this.props.onSelect.bind(this);
    }
    

    工作示例:

    &#13;
    &#13;
    const { Component } = React;
    
    class Child extends Component {
      constructor(props) {
        super(props);
        
        this.state = {
          selected: false
        };
        
        this.onSelect = this.props.onSelect.bind(this);
      }
    
      render() {
        const {selected} = this.state;
      
        return (
          <div>
            <input onSelect={this.onSelect} defaultValue="I'm the text" />
            
            <div>{selected ? 'selected' : 'not selected'}</div>
          </div>
        );
      }
    }
    
    class Parent extends Component {
      onSelect(e) {  
        this.setState({
          selected: !!e.target.value
        });
      }
      
      render() {
        return (
          <Child onSelect={this.onSelect} />
         )
      }
    }
    
    
    ReactDOM.render(
      <Parent />,
      demo
    );
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    
    <div id="demo"></div>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:1)

问题是您将onSelect定义为箭头函数,因此它会关闭this,而不是使用调用它的this。只需将其设为方法或非箭头功能:

class Parent extends React.Component {
  onSelect() {
    console.log(this.constructor.name);
    console.log(this.note);
  }
  render() {
    return <Child onSelect={this.onSelect} />;
  }
}
class Child extends React.Component {
  constructor(...args) {
    super(...args);
    this.note = "I'm the child";
  }
  render() {
    return (
      <button onClick={this.props.onSelect.bind(this)}>Click Me</button>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

但您可以考虑将onSelect 绑定一次而不是重复绑定{例如,不在render中),也许在Child的构造函数中。但是,只有将render称为批次才真正重要。 E.g:

class Parent extends React.Component {
  onSelect() {
    console.log(this.constructor.name);
    console.log(this.note);
  }
  render() {
    return <Child onSelect={this.onSelect} />;
  }
}
class Child extends React.Component {
  constructor(...args) {
    super(...args);
    this.note = "I'm the child";
    this.onSelect = this.props.onSelect.bind(this);
  }
  render() {
    return (
      <button onClick={this.onSelect}>Click Me</button>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>