我正在使用React中的计算器应用程序。我面临一些奇怪的问题。
问题在于If x = y Then
DoSomething
ElseIf x = z Then
DoSomethingElse
End If
功能。代码逻辑是将数字和运算符推送到computeResult()
,当用户单击calculationArray
按钮时,将调用=
函数。
我遇到的第一个问题是,当用户点击computeResult()
按钮时,最后一个操作符后面的最后一个数字或最后一个=
需要被推入expression
。我发现setState是异步的,所以我通过连接最后一个'表达式来创建一个新的数组calculationArray
。与tempcalculationArray
。然后使用calculationArray
循环计算总数。 for
从total
循环内部登录到控制台。
然后出现第二个问题,for
循环后的console.log
无效。
第三个问题是for
循环也无效后的setState
。
这是代码:
for

const Calculator = React.createClass({
getInitialState() {
return {
expression: "",
calculationArray: [],
answer: 0,
waitingForOperator: true,
};
},
inputDigit(val) {
const { expression, valueHolder, operator, waitingForOperator } = this.state;
this.setState({
expression: expression === "0" ? String(val) : expression + String(val),
waitingForOperator:true
});
},
inputDot() {
const { expression } = this.state;
if (expression.indexOf(".") == -1) {
this.setState({
expression: expression=="" ? "0." :expression + "."
});
}
},
inputSign() {
const { expression } = this.state;
if (expression.charAt(0) == "-") {
this.setState({
expression: expression.substr(1)
});
} else {
this.setState({
expression: "-" + expression
});
}
},
clearAll() {
const { expression , calculationArray, answer} = this.state;
this.setState({
expression: "",
calculationArray: [],
answer: 0
});
},
backSpace() {
const { expression } = this.state;
this.setState({
expression: expression.substr(0, expression.length - 1)
});
},
percent() {
const { expression } = this.state;
this.setState({
expression: String(Number(expression)/100)
});
},
inputOperator(oper) {
const { expression, calculationArray, waitingForOperator} = this.state;
if(waitingForOperator){
this.setState({
calculationArray: calculationArray.concat(expression).concat(oper),
expression:"",
waitingForOperator:false
});
}
},
computeResult() {
const { expression, calculationArray, waitingForOperator, answer} = this.state;
var arithmetic = {
'+': function (x, y) { return x + y },
'-': function (x, y) { return x - y },
'*': function (x, y) { return x * y },
'/': function (x, y) { return x / y },
};
var total = Number(calculationArray[0]);
var tempcalculationArray = calculationArray.concat(expression);
console.log(tempcalculationArray);
for(var i=1; i<=tempcalculationArray.length; i=i+2){
total = arithmetic[tempcalculationArray[i]](total, Number(tempcalculationArray[i+1]));
console.log(total);
}
console.log( "why I am not getting printed on console");
this.setState({
calculationArray: calculationArray.concat(expression),
waitingForOperator:false,
answer: total
});
},
render() {
const { expression, answer, math } = this.state;
const { updateExpression, computeResult } = this;
return (
<div>
<div id="displayarea">
<div id="equation"><p>{expression}</p></div>
<div id="answer"><p>{answer}</p></div>
</div>
<div id="calculatorpanel">
<div className="row">
<button className="btn" onClick={() => this.clearAll()}>AC</button>
<button className="btn" onClick={() => this.backSpace()}>←</button>
<button className="btn" onClick={() => this.inputOperator("/")}>÷</button>
<button className="btn" onClick={() => this.inputOperator("*")}>X</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(7)}>
7
</button>
<button className="btn" onClick={() => this.inputDigit(8)}>
8
</button>
<button className="btn" onClick={() => this.inputDigit(9)}>
9
</button>
<button className="btn" onClick={() => this.inputOperator("-")}>-</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(4)}>
4
</button>
<button className="btn" onClick={() => this.inputDigit(5)}>
5
</button>
<button className="btn" onClick={() => this.inputDigit(6)}>
6
</button>
<button className="btn" onClick={() => this.inputOperator("+")}>+</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(1)}>
1
</button>
<button className="btn" onClick={() => this.inputDigit(2)}>
2
</button>
<button className="btn" onClick={() => this.inputDigit(3)}>
3
</button>
<button className="btn" onClick={() => this.percent()}>%</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(0)}>
0
</button>
<button className="btn" onClick={() => this.inputSign()}>±</button>
<button className="btn" onClick={() => this.inputDot()}>.</button>
<button className="btn" onClick={() => this.computeResult()}>=</button>
</div>
</div>
<pre>{JSON.stringify(this.state, null, 2)}</pre>
</div>
);
}
});
ReactDOM.render(<Calculator />, document.getElementById("calculator"));
&#13;
#equation { border: 1px solid #ee82ee; }
#answer { border: 1px solid #00f; }
p { height: 1em; margin: 0; padding: .5em; }
&#13;
注意:在任何人提出这个问题之前,请注意我已经彻底搜索了stackflow问题并阅读了大部分问题,大部分答案都不适用于我的场景。此外,这个问题不可能重复,因为我正在寻找更好的方法来解决这个特定的问题。
答案 0 :(得分:2)
然后出现第二个问题,for循环后的
console.log
无效。第三个问题是for循环后的setState也无效。
我喜欢CodePen,但它的控制台很糟糕。特别是,它不会报告错误。如果您打开浏览器的内置JavaScript控制台并运行代码,当您点击=
按钮时,您会看到类似的错误:
Uncaught TypeError: arithmetic[tempcalculationArray[i]] is not a function
这是第二个和第三个问题的原因:当抛出错误时,代码会停止。
原因在于:
for(var i=1; i<=tempcalculationArray.length; i=i+2){
total = arithmetic[tempcalculationArray[i]](total, Number(tempcalculationArray[i+1]));
// ...
只要for
小于或等于 i
,就会运行此templcalcuationArray.length
循环。如果i
等于数组的长度,则它大于数组中最后一个元素的索引,下一行的tempcalculationArray[i]
将返回undefined
,{{1不是一个函数。
解决方案是使用undefined
运算符代替<
:
<=
这是一个工作片段:
for (var i = 1; i < tempcalculationArray.length; i += 2) {
const Calculator = React.createClass({
getInitialState() {
return {
expression: "",
calculationArray: [],
answer: 0,
waitingForOperator: true,
};
},
inputDigit(val) {
const { expression, valueHolder, operator, waitingForOperator } = this.state;
this.setState({
expression: expression === "0" ? String(val) : expression + String(val),
waitingForOperator:true
});
},
inputDot() {
const { expression } = this.state;
if (expression.indexOf(".") == -1) {
this.setState({
expression: expression=="" ? "0." :expression + "."
});
}
},
inputSign() {
const { expression } = this.state;
if (expression.charAt(0) == "-") {
this.setState({
expression: expression.substr(1)
});
} else {
this.setState({
expression: "-" + expression
});
}
},
clearAll() {
const { expression , calculationArray, answer} = this.state;
this.setState({
expression: "",
calculationArray: [],
answer: 0
});
},
backSpace() {
const { expression } = this.state;
this.setState({
expression: expression.substr(0, expression.length - 1)
});
},
percent() {
const { expression } = this.state;
this.setState({
expression: String(Number(expression)/100)
});
},
inputOperator(oper) {
const { expression, calculationArray, waitingForOperator} = this.state;
if(waitingForOperator){
this.setState({
calculationArray: calculationArray.concat(expression).concat(oper),
expression:"",
waitingForOperator:false
});
}
},
computeResult() {
const { expression, calculationArray, waitingForOperator, answer} = this.state;
var arithmetic = {
'+': function (x, y) { return x + y },
'-': function (x, y) { return x - y },
'*': function (x, y) { return x * y },
'/': function (x, y) { return x / y },
};
var total = Number(calculationArray[0]);
var tempcalculationArray = calculationArray.concat(expression);
console.log(tempcalculationArray);
for(var i=1; i<tempcalculationArray.length; i=i+2){
console.log(i, tempcalculationArray[i]);
total = arithmetic[tempcalculationArray[i]](total, Number(tempcalculationArray[i+1]));
console.log(total);
}
console.log( "why I am not getting printed on console");
this.setState({
calculationArray: calculationArray.concat(expression),
waitingForOperator:false,
answer: total
});
},
render() {
const { expression, answer, math } = this.state;
const { updateExpression, computeResult } = this;
return (
<div>
<div id="displayarea">
<div id="equation"><p>{expression}</p></div>
<div id="answer"><p>{answer}</p></div>
</div>
<div id="calculatorpanel">
<div className="row">
<button className="btn" onClick={() => this.clearAll()}>AC</button>
<button className="btn" onClick={() => this.backSpace()}>←</button>
<button className="btn" onClick={() => this.inputOperator("/")}>÷</button>
<button className="btn" onClick={() => this.inputOperator("*")}>X</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(7)}>
7
</button>
<button className="btn" onClick={() => this.inputDigit(8)}>
8
</button>
<button className="btn" onClick={() => this.inputDigit(9)}>
9
</button>
<button className="btn" onClick={() => this.inputOperator("-")}>-</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(4)}>
4
</button>
<button className="btn" onClick={() => this.inputDigit(5)}>
5
</button>
<button className="btn" onClick={() => this.inputDigit(6)}>
6
</button>
<button className="btn" onClick={() => this.inputOperator("+")}>+</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(1)}>
1
</button>
<button className="btn" onClick={() => this.inputDigit(2)}>
2
</button>
<button className="btn" onClick={() => this.inputDigit(3)}>
3
</button>
<button className="btn" onClick={() => this.percent()}>%</button>
</div>
<div className="row">
<button className="btn" onClick={() => this.inputDigit(0)}>
0
</button>
<button className="btn" onClick={() => this.inputSign()}>±</button>
<button className="btn" onClick={() => this.inputDot()}>.</button>
<button className="btn" onClick={() => this.computeResult()}>=</button>
</div>
</div>
<pre>{JSON.stringify(this.state, null, 2)}</pre>
</div>
);
}
});
ReactDOM.render(<Calculator />, document.getElementById("calculator"));
#equation { border: 1px solid #ee82ee; }
#answer { border: 1px solid #00f; }
p { height: 1em; margin: 0; padding: .5em; }