65535
65535

Reputation: 553

React: How to force setState()?

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

Answers (1)

user14311453
user14311453

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

Related Questions