Reputation: 553
In this React Javascript Calculator this.setState({ array: displayed});
is supposed to update the array in state, but it doesn't. Is there a way to force it? Any help would be greatly appreciated.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';
class JavascriptCalculator extends React.Component {
constructor(props) {
super(props);
this.state = {
text: 0,
array: [],
operators:['+']
}
this.display = this.display.bind(this);
this.clear = this.clear.bind(this);
this.calculate = this.calculate.bind(this);
}
display(text){
// if display is zero, remove the leading zero from the text.
if(this.state.text == 0){
this.state.text = ''
}
let regex = /[*/+-]/;
// if text is not an operator
if (!regex.test(text)){
let displayed = this.state.text
// disallow consecutive decimal points
if (text == '.' && displayed.slice(-1) == '.'){
return;
}
// start by adding text
displayed = this.state.text += text;
// disallow multiple decimal points in a number
// if attempt at more than one decimal point remove last one.
let array = displayed.split('');
let count = 0;
for (let i = 0; i < array.length; i++){
if (array[i] == '.'){
count++;
}
}
// one decimal point is allowed per operator.
// thus to allow the first decimal point,
// this.state.operators must be initialized
// to length of 1.
if(count > this.state.operators.length){
array.pop();
}
displayed = array.join('');
this.setState({ text: displayed});
}
// if text is an operator
if (regex.test(text)){
// add the text to the array
// so that repeated decimal points are prevented
let array = this.state.operators;
array.push(text);
this.setState({ operators: array});
// add the text to the text
let displayed = this.state.text += text;
this.setState({ text: displayed});
}
// if text ends in equals sign, run the calculate function.
if (text == '='){
let displayed = this.state.text.split('');
console.log(displayed);
this.setState({ array: displayed});
//this.state.array = displayed;
this.calculate();
}
}
calculate(){
let regex = /[*/+-]/;
let text = '';
let length = this.state.array.length;
let operators = [];
//console.log(this.state.array);
// capture numbers longer than one digit by adding them to a string
// and adding a comma in place of the operators, so the string
// can be split into an array at the operators.
for (let i = 0; i < length; i++){
// put numbers into a string
if (this.state.array[i].match(/[\d.]/)) {
text+=this.state.array[i];
}
// add commas to string in place of operators
if (this.state.array[i].match(regex)){
text+=',';
// add operators to their own array
operators.push(this.state.array[i]);
}
if (this.state.array[i] == '='){
break;
}
}
//console.log(operators);
// create the numbers array
let numbers = text.split(',');
//console.log(numbers);
// initialize answer with first number
let answer = numbers[0];
let func = undefined;
// Start with second number
for (let i = 1; i < numbers.length; i++){
func = returnFunc(operators.shift());
console.log(func);
answer = func(answer, numbers[i]);
}
this.display(answer);
function returnFunc(val) {
switch (val) {
case '+':
return function sum(a,b) { return Number(a)+Number(b)};
case '-':
return function subtract(a,b) { return Number(a)-Number(b)};
case '*':
return function multiply(a,b) { return Number(a)*Number(b)};
case '/':
return function divide(a,b) { return Number(a)/Number(b)};
default:
throw new Error("Called with unknown operator " + val);
}
}
}
clear(id){
this.setState({ text: id });
this.setState({ array: [] });
this.setState({ operators: [] });
}
render() {
return (
<div id="javascript-calculator">
<h1 id="title">Javascript Calculator</h1>
<div id="display">{this.state.text}</div>
<hr/>
<div>
<button id="clear" onClick={e => this.clear("0")}> clear </button>
<button id="equals" onClick={e => this.display("=")}> = </button>
<button id="zero" onClick={e => this.display("0")}> 0 </button>
<button id="one" onClick={e => this.display("1")}> 1 </button>
<button id="two" onClick={e => this.display("2")}> 2 </button>
<button id="three" onClick={e => this.display("3")}> 3 </button>
<button id="four" onClick={e => this.display("4")}> 4 </button>
<button id="five" onClick={e => this.display("5")}> 5 </button>
<button id="six" onClick={e => this.display("6")}> 6 </button>
<button id="seven" onClick={e => this.display("7")}> 7 </button>
<button id="eight" onClick={e => this.display("8")}> 8 </button>
<button id="nine" onClick={e => this.display("9")}> 9 </button>
<button id="add" onClick={e => this.display("+")}> + </button>
<button id="subtract" onClick={e => this.display("-")}> - </button>
<button id="multiply" onClick={e => this.display("*")}> * </button>
<button id="divide" onClick={e => this.display("/")}> / </button>
<button id="decimal" onClick={e => this.display(".")}> . </button>
</div>
</div>
);
}
}
ReactDOM.render(<JavascriptCalculator />, document.getElementById("app"));
index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Javascript Calculator</title>
<style>
</style>
</head>
<body>
<main>
<div id="app"></app>
</main>
</body>
</html>
Upvotes: 0
Views: 344
Reputation:
setState is async. It won't work how you're using it. In your case, you should just pass the displayed
array to the calculate function.
Upvotes: 1