This question already has an answer here:
I'm trying build my first calculator in React.
There seems to be a problem with my buttons (I think).
While testing with console.log
s, I discovered my first click of the addition button does NOT update all the setStates. Instead, the second click updates it correctly.
ANY idea why it isn't working?
import React, { Component } from 'react';
class calculator extends Component {
state = {
xxxxx:0,
v1:0,
v2:0,
isCal:null
}
makeAdd = () => {
const firstNum = this.state.xxxxx;
this.setState({
v1:firstNum,
xxxxx:0,
isCal:"add"
});
console.log("Add, firstNum is " + firstNum );
console.log("and v1 is: " + this.state.v1);
console.log("and isCal is: " + this.state.isCal);
document.getElementById('DaInserting').innerHTML = null;
};
okInsert = (num) => {
let ss = document.getElementById('DaInserting').innerHTML += num;
this.setState({xxxxx:ss})
}
deAnswer = () => {
let SecondNum = this.state.xxxxx;
this.setState({v2:SecondNum})
console.log("deSecond :" + this.state.v2);
console.log("this.setState.isCal :" + this.state.isCal);
let answer = 0;
this.setState.v2 = this.state.xxxxx;
if(this.state.isCal==="add") {
answer = this.state.v1 + this.state.v2;
console.log("and the answer is :" + answer);
}
document.getElementById('DaInserting').innerHTML = answer;
//this.thenReset();
}
thenReset = () => {
if (this.setState.isCal !== null) {
this.setState({xxxxx:0})
this.setState({v1:0})
this.setState({v2:0})
this.setState({isCal:null})
}
}
render() {
//console.log("\nALL states\nthis.state.xxxxx :" + this.state.xxxxx + "\nthis.state.v1 :"+ this.state.v1);
return (
<div className="container">
<div className="row">
<div style={{height:64}} className="col-12 card-body m-2 shadow-sm rounded bg-light" id="DaInserting"> </div>
</div>
<div className="row">
<div className="col-3"><div onClick={() => this.okInsert(7)} className="btn btn-secondary btn-lg m-2 btn-block ">7</div></div>
<div className="col-3"><div onClick={() => this.okInsert(8)} className="btn btn-secondary btn-lg m-2 btn-block ">8</div></div>
<div className="col-3"><div onClick={() => this.okInsert(9)} className="btn btn-secondary btn-lg m-2 btn-block ">9</div></div>
<div className="col-3"><div onClick={this.makeDivide} className="btn btn-primary btn-lg m-2 btn-block ">/</div></div>
</div>
<div className="row">
<div className="col-3"><div onClick={() => this.okInsert(4)} className="btn btn-secondary btn-lg m-2 btn-block ">4</div></div>
<div className="col-3"><div onClick={() => this.okInsert(5)} className="btn btn-secondary btn-lg m-2 btn-block ">5</div></div>
<div className="col-3"><div onClick={() => this.okInsert(6)} className="btn btn-secondary btn-lg m-2 btn-block ">6</div></div>
<div className="col-3"><div onClick={this.makeMultiply} className="btn btn-primary btn-lg m-2 btn-block ">x</div></div>
</div>
<div className="row">
<div className="col-3"><div onClick={() => this.okInsert(1)} className="btn btn-secondary btn-lg m-2 btn-block ">1</div></div>
<div className="col-3"><div onClick={() => this.okInsert(2)} className="btn btn-secondary btn-lg m-2 btn-block ">2</div></div>
<div className="col-3"><div onClick={() => this.okInsert(3)} className="btn btn-secondary btn-lg m-2 btn-block ">3</div></div>
<div className="col-3"><div onClick={this.makeSubtract} className="btn btn-primary btn-lg m-2 btn-block ">-</div></div>
</div>
<div className="row">
<div className="col-6"><div onClick={this.deAnswer} className="btn btn-warning btn-lg m-2 btn-block ">=</div></div>
{/* <div className="col-3"><div onClick={() => this.okInsert(".")} className="btn btn-secondary btn-lg m-2 btn-block ">.</div></div> */}
<div className="col-3"><div onClick={() => this.okInsert(0)} className="btn btn-secondary btn-lg m-2 btn-block ">0</div></div>
<div className="col-3"><div onClick={this.makeAdd} className="btn btn-primary btn-lg m-2 btn-block ">+</div></div>
</div>
</div>
);
}
}
export default calculator;
I have a div called "DaInserting" while gets updated as the user clicks on any number keys, then when the user will click on addition/subtraction/etc, v1
should get updated, but it doesn't. It gets updated on the second click:- check console.log
.
After the user has clicked additions/subtraction, "DaInserting" gets a reset, user clicks some numbers again, and then clicks the result button which should then check what the user choose (addition/subtraction)
It tested your code and it is updating the state correctly, remember that setState() is an asynchronous function, so if you wanna check correctly add the function as a callback to be executed after the state is updated, like this:
this.setState({ v1:firstNum, xxxxx:0, isCal:"add"}, () => {
console.log("Add, firstNum is " + firstNum );
console.log("and v1 is: " + this.state.v1);
console.log("and isCal is: " + this.state.isCal);
console.log(news)
});
In React, setState
is asynchronous (see these docs for more on this), so you cannot rely on state updating right after calling setState
. Instead, you generally need to wait until the next render for state values to update.
To get around this, you can pass a callback function (as a second argument) to setState
, or use await
, or use the new values that you're updating state with directly. Here I'd recommend using that last option. Also, it's usually a good idea to only call setState
right before exiting a function, to avoid async confusion.
Here is an example how you might update the deAnswer
method:
deAnswer = () => {
let answer = 0;
if (this.state.isCal === "add") {
answer = this.state.v1 + this.state.xxxxx;
console.log("and the answer is :" + answer);
}
this.setState({
v2: this.state.v1,
answer: answer,
})
}
render() {
return (
<div className="row">
<div id="DaInserting">{ this.state.answer }</div>
</div>
)
}
Note also I've removed the setting of innerHTML
, since you can and should change the content of the "DaInserting"
div through rendering with state variables, not direct DOM manipulation.
Also consider checking out the Intro to React Tutorial, it's a nice read and will help you in learning and building with React.
Firebase Cloud Functions: PubSub, "res.on is not a function"
TypeError: Cannot read properties of undefined (reading 'createMessageComponentCollector')
I'm trying to set up proxies for the player and opponent characters for this game I'm makingBasically I want the game to print the gameover screen when the player / opponent's health are set to 0
I'm running a function on an intervalI need to get element by class name, use the id of each and pass it into a function as a variable
I've implemented my calls to the back-end for this tiny part of my system with Promises using the reduce() pattern as such: