0

I am trying to create a counter button but I can't. I know its something to do with binding but I can't find a solution. I tried by using .bind(this) but its does not work.

class Button extends React.Component{
  render(){
    return(
      <button onClick={this.props.localHandleClick}>+1</button>
    )
  }
}
class Result extends React.Component{
  render(){
    return (
      <div>{this.props.localCounter}</div>
    )
      
  }
}
class Main extends React.Component{
  constructor(props){
    super(props);
    this.state={
      counter:0
    }
  }
   clickHandler(){
    this.setState({counter:                   
    this.state.counter+1});
  }
  render(){
    return(
      <div>
        <Button localHandleClick={this.handleClick}/>
        <Result localCounter={this.state.counter} />        
      </div>
    )
      
  }
}
ReactDOM.render(
  <Main />,
  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>
Krishna Rana
  • 379
  • 1
  • 2
  • 11
  • 1
    Add this to your constructor - `this.clickHandler = this.clickHandler.bind(this)`. – Ori Drori Jul 12 '17 at 19:53
  • Possible duplicate of [OnClick Event binding in React.js](https://stackoverflow.com/questions/27397266/onclick-event-binding-in-react-js) – E_net4 Jul 12 '17 at 19:53
  • I have tried this. This does not work. – Krishna Rana Jul 12 '17 at 19:55
  • @KrishnaRana What is the error you get? – Giorgi Moniava Jul 12 '17 at 19:56
  • I don't get any error, but the screen is blank – Krishna Rana Jul 12 '17 at 19:58
  • add this in constructor of main component: `this.handleClick = this.handleClick.bind(this)` – Mayank Shukla Jul 12 '17 at 19:59
  • @KrishnaRana you said you don't get an error and the screen is blank? Your question example doesn't appear as blank -- maybe update it with the new code so we can see what the issue is? – aug Jul 12 '17 at 20:01
  • @aug error is the button doesn't work. And when I add this.handleClick = this.handleClick.bind(this) the screen is blank – Krishna Rana Jul 12 '17 at 20:03
  • @KrishnaRana Did anyone solve your problem? If so, could you please accept the best answer (click the checkmark under the points). That will help other users that come across your question quickly spot the accepted answer and it also gives 15 rep. points to the author (: – Danziger Jan 31 '18 at 05:02

2 Answers2

1

Changes:

1. Bind handleClick method in the constructor of main component.

2. There is a name mismatch, you are passing the handleClick method but you defined the clickHandler. Replace clickHandler by handleClick.

Check the working snippet:

class Button extends React.Component{
  render(){
    return(
      <button onClick={this.props.localHandleClick}>+1</button>
    )
  }
}

class Result extends React.Component{
  render(){
    return (
      <div>{this.props.localCounter}</div>
    )
      
  }
}

class Main extends React.Component{
  constructor(props){
    super(props);
    this.state={
      counter:0
    }
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(){
    this.setState({counter: this.state.counter+1});
  }

  render(){
    return(
      <div>
        <Button localHandleClick={this.handleClick}/>
        <Result localCounter={this.state.counter} />     
      </div>
    )
      
  }
}

ReactDOM.render(
  <Main />,
  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'/>
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
0

Just use .bind(this) on your handler so that this refers to the component instead of being undefined.

Note this is not specific to React, but the default behaviour of JavaScript class methods, which are not automatically bound.

Also, you are using different names in the handler definition and when you use it in the template.

class Button extends React.Component {

  render() {
    return(
      <button onClick={this.props.localHandleClick}>+1</button>
    );
  }
}

class Result extends React.Component {

  render() {
    return(
      <div>{this.props.localCounter}</div>
    );  
  }
}

class Main extends React.Component {

  constructor(props) {
    super(props);
    
    this.state = {
      counter: 0,
    };
    
    this.handleClick = this.handleClick.bind(this)
  }
  
  handleClick() {
    this.setState({
      counter: this.state.counter + 1,
    });
  }
  
  render() {
    return(
      <div>
        <Button localHandleClick={ this.handleClick }/>
        <Result localCounter={ this.state.counter } />        
      </div>
    );
  }
}

ReactDOM.render(<Main />, 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>

If you are using Babel's class property transform, you can declare your handler as follows, and it will be automatically bound:

class Main extends React.Component {

    handleClick = () => {
        this.setState({
            counter: this.state.counter + 1,
        });
    };

    constructor(props) { ... }

    render() { ... }
}
Danziger
  • 19,628
  • 4
  • 53
  • 83