我正在尝试在React中构建我的第一个计算器。
我的按钮似乎有问题(我认为)。
在测试console.log
时,我发现我第一次点击加法按钮并不会更新所有setState。相反,第二次单击可以正确更新它。
知道为什么它不起作用吗?
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;
我有一个称为“ DaInserting”的div,当用户单击任何数字键时会进行更新,然后当用户单击加/减/等时,v1
应该会更新,但不会更新。单击第二次即可更新:-选中console.log
。
用户单击加/减后,“ DaInserting”将重置,用户再次单击一些数字,然后单击结果按钮,然后应检查用户选择的内容(加/减)
答案 0 :(得分:2)
在React中,setState
是异步的(有关更多信息,请参见these docs),因此您不能在调用setState
之后立即依赖状态更新。取而代之的是,您通常需要等到下一个渲染状态值才能更新。
要解决此问题,您可以将回调函数(作为第二个参数)传递给setState
,或使用await
,或使用直接更新状态的新值。在这里,我建议您使用最后一个选项。另外,通常最好在退出函数之前仅调用setState
,以避免异步混乱。
以下是如何更新deAnswer
方法的示例:
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>
)
}
请注意,我已经删除了innerHTML
的设置,因为您可以并且应该通过使用状态变量进行渲染而不是直接进行DOM操作来更改"DaInserting"
div的内容。
也可以考虑阅读Intro to React Tutorial,这是一本不错的书,它将帮助您学习和使用React进行构建。
答案 1 :(得分:2)
它测试了您的代码,并且正在正确更新状态,请记住setState()是一个异步函数,因此,如果您要检查是否正确添加了该函数作为要在状态更新后执行的回调,如下所示:< / p>
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)
});