React - 为什么在这个例子中不需要绑定?

时间:2017-01-26 05:10:19

标签: reactjs binding

试图弄清楚React的基础知识。

查看此页面上的第二个示例:https://facebook.github.io/react/ 我看到tick()函数设置Timer类的状态,将前一个值递增一个。

class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {secondsElapsed: 0};
  }

  tick() {
    this.setState((prevState) => ({
      secondsElapsed: prevState.secondsElapsed + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return (
      <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
    );
  }
}

ReactDOM.render(<Timer />, mountNode);

然而,当我尝试实现我自己的简单Counter类时,它失败了,我得到一个控制台错误,说无法读取未定义的属性setState。

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {count: 0};
    }

    increment(prevState) {
        this.setState((prevState) => ({
            count: prevState.count + 1
        }));
    }

  render() {
    return (
            <div className="main">
                <button onClick={this.increment}>{this.state.count}</button>
            </div>
    )
  }
}

一些谷歌搜索显示我必须将它绑定到增量函数。但是为什么在我看到的第一个例子中不需要这个?我将代码复制到CodePen,它与React 15.3.1运行良好我在该示例中找不到任何类似绑定的内容。只有在我在构造函数中添加了绑定代码后,才会在我的示例中开始工作。

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {count: 0};

        // THIS ONE LINE FIXED THE ISSUE
        this.increment = this.increment.bind(this);
    }

    increment(prevState) {
        this.setState((prevState) => ({
      count: prevState.count + 1
    }));
    }

  render() {
    return (
            <div className="main">
                <button onClick={this.increment}>{this.state.count}</button>
            </div>
    )
  }
}

2 个答案:

答案 0 :(得分:15)

回答您的问题:第一个示例使用function matchingCounts(str1, str2) { const counts = countChars(str1 + str2); Object.keys(counts).forEach(chr => { if (!str1.includes(chr) || !str2.includes(chr)) delete counts[chr]; }); return counts; } ,自动执行context binding。来自文档:

  

箭头函数不会创建自己的上下文,所以这有   它的原始含义来自封闭的语境。

确实在React中有一些绑定方式:

1)你可以bind构造函数中的所有函数,就像你说的那样:

arrow functions

2)用箭头函数调用你的回调:

constructor(props) {
    /* ... */
    this.increment = this.increment.bind(this);
}

3)每次将其设置为回调时,在方法引用的末尾附加.bind,如下所示:

<button onClick={(e) => this.increment(e)}>

4)在您的班级中,使用箭头功能定义方法:

<button onClick={this.increment.bind(this)}>

要在babel中使用此语法,您必须启用此plugin或使用stage-2预设。

答案 1 :(得分:1)

如果仔细查看第一个示例中调用tick()函数的方式,您将理解在使用arrow functions调用时已为其指定了绑定。如果你对增量函数做同样的事情,它也会起作用。这些只是绑定功能的不同方式。

所以问到,并不是在第一个例子中没有指定绑定,而是在它需要的第二个例子中,而在你的两种情况下,你绑定的只是两种情况的绑定方式不同。

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {count: 0};

        
       
    }

    increment(prevState) {
        this.setState((prevState) => ({
      count: prevState.count + 1
    }));
    }

  render() {
    return (
            <div className="main">
                <button onClick={() => this.increment()}>{this.state.count}</button>
            </div>
    )
  }
}

ReactDOM.render(<Counter/>, document.getElementById('app'));
<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="app"></div>