React calculator: problem with binding methods

I´m trying to make a click handler event that will handle all the calculation operations. I keep getting a error when compiling. I´ve tried everything, but I can´t seem to solve it. I think I´m binding the method wrong inside the class, but I am not sure (the “Button” is a different functional component).

What does the console show for the specific error?

Tried that, sitll doesn´t work

Try moving handleClick() OUTSIDE of the constructor function, but still inside your component.

1 Like

I moved it, I think, but still getting the same error (but on a different line!):

Something I might suggest (don’t know if it’ll help, but it’s good practice while I’m looking at other things – don’t use event as a parameter. It’s a part of the javascript language itself, should be a reserved keyword. Rather, do sommething like:

handleClick(evt){
  const answer = evt.target.id;
  // the rest of your code...
}
1 Like

Thank you. I changed it, but still doesn´t solve the problem.

According to what I’m seeing, the error is in the handleClick function, and may have nothing to do with a semicolon. When you setState() in the handleClick(), what state property is that array being assigned to?

1 Like

I solved it, I was setting value wrong. Stupid mistake!
But I can´t seem to get the function to push the button´s values into the value array:

So you want to concatenate the current result onto this.state.value – how about this.setState({value : this.state.value.concat(result) })

That preserves the original value array, and adds that one value on. This wasn’t my idea, took it from stackOverflow.

Nope, not working. Don´t know what I´m doing wrong.

Have you read https://www.robinwieruch.de/react-state-array-add-update-remove/

1 Like

Yeah, but even changing the array into a string doesn´t solve it:

Well, it wouldn’t. I assume that last one simply replaces the current value with result, rather than pushing it onto a stack. Try

handleClick(evt){
  const result= evt.target.value;
  this.setState({ value : [...this.state.value, result] } )
 }

Basically does the same thing as concat(), using the spread operator. Do you have this running somewhere that we can hammer on it a little?

1 Like

All these Button components in the return method break the DRY principle. You need to generate them dynamically. UseReact.cloneComponent or a higher-order component to add the onclick for all at once instead of doing it manually for each.

1 Like

Thank you. I looked it up, but don´t know how to pass props to the CloneComponent.

I´ll throw it on a Codepen!

If you want to pass a prop called ‘newProp’ with the value ‘valueProp’, then your new element will be React.cloneElement(element, {newProp: 'valueProp}), where element = <Button onClick={handler}/>.
I stand corrected, you cannot pass onClick with cloneComponent, but you don’t have to, as I did it by adding to the JSX element directly. Then you can pass an array with the values and id (why not just name them all from 1 to 16 to make it easier, and then in the handler use a switch to interpret). So you get something like this:

let i = 0;
let arr = []
while (i<16){
  arr.push(i++);
}

Then, in the return method in render:

return (
  <div>
    <Display id="display" value={this.state.value} />
   {arr.map(el => <Button onClick={this.handleClick} key={el} id={el} value={el} />)}
  </div>
);

Then in the hadler add a switch in which you interpret what is happening if value is a certain number and so on. I think the code looks much better and it does not even use use React.cloneComponent.

1 Like

I believe you want to pass your value to the function as an argument instead of assigning it as a value to the button.

So in your code you can have handleClick:

handleClick(val) {
this.setState({value: this.state.concat(val)});
}

then on the button:

<Button onClick={() => this.handleClick("/")} id="divide"  />
1 Like

I can´t do that because the challenge has strict rules about the ID names.