problems with this in Reactjs

Asked

Viewed 86 times

1

The problem is this: I’m trying to build an accountant to practice mine React and an error occurred:

this is undefined

I created a state to hold the minutes and seconds:

constructor(props) {
    super(props)
    this.state = {
        min: 0,
        seg: 0,
    }
}

I called you both there to my surrender:

render() {
    const { min, seg } = this.state;
    return (
        <React.Fragment>
            <p>{min}:{seg}</p>
            <button onClick={this.startCountdown}>Start</button>
            <button>Stop</button>
            <button>Reset</button>
        </React.Fragment>
    )
}

and then and went to create the function to start counting. Look, at first I don’t want the logic of decrementation, I was trying to simply change the values on the screen by clicking on startCowndown, but I had the return of error this is undefined.

My function to change the values on the screen was like this:

startCountdown () {
    let {min, seg} = this.state;
    this.setState({min: 1, seg: 59})
}

Well, it didn’t work, so I thought it would be unnecessary to call min and seg with the destructuring since I was already using the method setState, so I took.

startCountdown(){
    this.setState({min: 1, seg: 59})
}

and yet this is Undefined continues to appear.

Could someone explain to me why this behavior?

  • 2

    missing Arrow Function. <button onClick={() => this.startCountdown}>Start</button> and in the method startCountdown () => {...

  • 1

    and another need not do the descruct, correct method startCountdown () => {&#xA; this.setState({min: 1, seg: 59})&#xA;}

  • 1

    Take a look with Hooks https://codesandbox.io/s/epic-hugle-hq4x5

  • your solutions are perfect, but none of them worked or would even work, precisely because I was calling the onClick function not in a tag, but in the Button component. <Button onClick={startPomodoro}/> After I made the call inside the tag all the presented solutions started to work.

  • what contradiction.

2 answers

1

Because the mistake happened?

How much do you work with classes in react, the methods in react need to say in what context it belongs and with bind(this) solves this problem. There are ways to solve this, one of them is by constructor or even do on the button or component itself, example:

class Source extends React.Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };
    this.handleIncrement = this.handleIncrement.bind(this);
  }
  handleIncrement() {
    const count = this.state.count + 1;
    this.setState({ count });
  }
  render() {
    return (
      <div>
        <div>{this.state.count}</div>
        <button onClick={this.handleIncrement}>Increment</button>
      </div>
    );
  }
}
ReactDOM.render( <Source/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

or in itself onClick:

class Source extends React.Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };    
  }
  handleIncrement() {
    const count = this.state.count + 1;
    this.setState({ count });
  }
  render() {
    return (
      <div>
        <div>{this.state.count}</div>
        <button onClick={this.handleIncrement.bind(this)}>Increment</button>
      </div>
    );
  }
}
ReactDOM.render( <Source/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

or even declares an anonymous function that simplifies and does not have to use the bind(this):

class Source extends React.Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };  
  }
  handleIncrement = () => {
    const count = this.state.count + 1;
    this.setState({ count });
  }
  render() {
    return (
      <div>
        <div>{this.state.count}</div>
        <button onClick={this.handleIncrement}>Increment</button>
      </div>
    );
  }
}
ReactDOM.render( <Source/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

In your code I would do so:

class Source extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
        min: 0,
        seg: 0,
    }
    this.startCountdown =
      this.startCountdown.bind(this);
  }
  startCountdown () {
    let {min, seg} = this.state;
    this.setState({min: 1, seg: 59})
  }
  render() {
    const { min, seg } = this.state;
    return (
        <React.Fragment>
            <p>{min}:{seg}</p>
            <button onClick={this.startCountdown}>Start</button>
            <button>Stop</button>
            <button>Reset</button>
        </React.Fragment>
    )
}
}
ReactDOM.render( <Source/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Pronto worked.

At the present time we use more Hooks that simplifies this process take a look at the syntax written by this answer

0


Antony,

Strange error occur saying the context this is undefined. I needed to see the full code.

However, I made a sandbox implementing exactly what you want to achieve, you can give a analyzed and check what may be wrong.

https://codesandbox.io/s/contador-eops1

One important thing to remember is the fact of using the bind. In order for a Function within a class to have the same class context, for example, it is necessary to use a method called bind.

Look at the code inside the constructor:

constructor(props) {
 super(props);
 this.startCountdown = this.startCountdown.bind(this);
}

state = {
 min: 0,
 seg: 0
};

startCountdown() {
 this.setState({ min: 1, seg: 59 });
}

The code is working now.

Any questions, comment on that answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.