[Video included] JavaScript Calculator State Not Updating Correctly

Tell us what’s happening:
I’m attempting to get the “formula” section of my calculator to work, and I’ve run into an issue that I think is related to lifecycle events, but can’t figure out what exactly is going on.

Basically, I’ve created a function called “handleFormula,” which is called when the program detects that an operator (±/x) has been entered and is followed by a number or decimal. The function is then supposed to check if there is a single 0, or the words “Push a button” in the formula field, clear it, and then concat what was in the display to the formula.

Even when the if statements in handleFormula are called, however, the state does not update correctly, and the display ends up getting concatenated to the words “Push a button” or to the “0.”

Here’s a video to illustrate what I mean: https://youtu.be/7wgtXKbMq4s

Your code so far

import React, { Component } from "react";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import "./App.css";

const operators = /[+\-x/]/g;
const letters = /[a-z]/i;

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      display: "0",
      formula: "Push a button"
    };

    this.handleInput = this.handleInput.bind(this);
    this.handleClear = this.handleClear.bind(this);
    this.handleFormula = this.handleFormula.bind(this);
  }

  //Logic for display
  handleInput(x) {
    console.log(letters.test(this.state.formula));
    //console.log(operators.test(x));
    //console.log(operators.test(this.state.display));
    //Checks if part of the formula is complete and the display needs to be reset
    if (operators.test(this.state.display) && operators.test(/[0-9]/)) {
      console.log("Calling handleFormula()");
      this.handleFormula(this.state.display);
      this.setState({ display: "0" });
    }
    //Doesn't allow for multiple starting 0s
    else if (this.state.display === "0" && x === "0") {
      this.setState({ display: "0" });
      return;
    }
    //Allows for operators to follow a zero
    else if (x.match(operators)) {
      this.setState({ display: this.state.display + x });
    }
    //Removes the default 0 if preceding conditions aren't met
    else if (x !== 0 && x !== "." && this.state.display === "0") {
      this.setState({ display: x });
    }
    //Doesn't allow for consecutive decimals
    else if (this.state.display.match(/\.{1,}/g) && x == ".") {
      return;
    }
    //Otherwise concat x to the string
    else {
      this.setState({ display: this.state.display + x });
      return;
    }
  }

  //Clears the display and formula fields
  handleClear() {
    this.setState({ display: "0", formula: "0" });
    return;
  }

  //Moves the numbers and operators from the display to the formula box
  handleFormula(y) {
    console.log("handleFormula() called");
    if (letters.test(this.state.formula)) {
      console.log("Non-numbers cleared");
      this.setState({ formula: "" });
      this.forceUpdate();
    } else if (this.state.formula === "0") {
      console.log("Single 0 cleared");
      this.setState({ formula: "" });
      this.forceUpdate();
    }
    console.log("Formula updated");
    this.setState({ formula: this.state.formula + y });
  }

  //The calculator
  render() {
    return (
      <React.Fragment>
        <div className="col-md-6" />
        <div className="container col-md-3">
          <div className="row">
            <div id="formula" className="container-fluid">
              {this.state.formula}
            </div>
          </div>
          <div className="row">
            <div id="display" className="container-fluid">
              {this.state.display}
            </div>
          </div>

          <div className="row">
            <button
              id="clear"
              className="col-9 btn btn-danger"
              onClick={() => this.handleClear()}
            >
              C
            </button>
            <button
              id="divide"
              className="col-3 btn btn-primary"
              onClick={() => this.handleInput("/")}
            >
              /
            </button>
          </div>
          <div className="row">
            <button
              id="seven"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("7")}
            >
              7
            </button>
            <button
              id="eight"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("8")}
            >
              8
            </button>
            <button
              id="nine"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("9")}
            >
              9
            </button>
            <button
              id="multiply"
              className="col-3 btn btn-primary"
              onClick={() => this.handleInput("x")}
            >
              x
            </button>
          </div>
          <div className="row">
            <button
              id="four"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("4")}
            >
              4
            </button>
            <button
              id="five"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("5")}
            >
              5
            </button>
            <button
              id="six"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("6")}
            >
              6
            </button>
            <button
              id="subtract"
              className="col-3 btn btn-primary"
              onClick={() => this.handleInput("-")}
            >
              -
            </button>
          </div>
          <div className="row">
            <button
              id="one"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("1")}
            >
              1
            </button>
            <button
              id="two"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("2")}
            >
              2
            </button>
            <button
              id="three"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput("3")}
            >
              3
            </button>
            <button
              id="add"
              className="col-3 btn btn-primary"
              onClick={() => this.handleInput("+")}
            >
              +
            </button>
          </div>
          <div className="row">
            <button
              id="zero"
              className="col-6 btn btn-secondary"
              onClick={() => this.handleInput("0")}
            >
              0
            </button>
            <button
              id="decimal"
              className="col-3 btn btn-secondary"
              onClick={() => this.handleInput(".")}
            >
              .
            </button>
            <button id="equals" className="col-3 btn btn-primary">
              =
            </button>
          </div>
        </div>
        <div className="col-md-6" />
      </React.Fragment>
    );
  }
}

export default App;

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0.

Link to the challenge: