[Help] Calculator (using React hooks)

Tell us what’s happening:

I can’t get it works. It seems that my computation() is not called in chooseTheOperator(operator) .
I am not sure how to fix it.
can anyone help me?
Thank you very much.

Your code so far

import React, { useState } from "react";
import "./App.css";

function App() {
  const [currentValue, setCurrentValue] = useState("0");
  const [preValue, setPreValue] = useState("");
  const [storeTheValue, setStoreTheValue] = useState(undefined);
  const [waitForTheNextNum, setWaitForTheNextNum] = useState(false);

  function handleClick(e) {
    const { value } = e.target;
    appendNum(value);
    allClear(value);
  }

  function appendNum(number) {
    if (number === "." && currentValue.includes(".")) return;
    if (!isNaN(number)) {
      setCurrentValue(currentValue + number);
    }

    if (currentValue === "0") {
      setCurrentValue(number);
    }
  }

  function chooseTheOperator(operator) {
    const { value } = operator.target;
    setWaitForTheNextNum(true);
    setStoreTheValue(value);

    if (value !== undefined && preValue === "") {
      setPreValue(currentValue);
      setCurrentValue("");
    }
    if (preValue !== "" && waitForTheNextNum) {
      computation();
    }
  } //hasProblem

  console.log("Prevalue:", preValue, "currentValue:", currentValue);

  function computation() {
    let num;
    switch (storeTheValue) {
      case "+":
        num = parseFloat(preValue) + parseFloat(storeTheValue);
        return num;
        break;
      case "-":
        num = parseFloat(preValue) - parseFloat(storeTheValue);
        return num;
        break;
      case "X":
        num = parseFloat(preValue) * parseFloat(storeTheValue);
        return num;
        break;
      case "/":
        num = parseFloat(preValue) / parseFloat(storeTheValue);
        return num;
        break;
        default: return;
        console.log("running on Switch");
    }

    setCurrentValue(num);
    setStoreTheValue(undefined);
    setPreValue("");
    setWaitForTheNextNum(false);
  }
  //hasProblem. 

  function clearTheNumber() {
    setCurrentValue(currentValue.slice(0, -1));
  }

  function allClear(button) {
    if (button === "allClear") {
      setCurrentValue("0");
      setPreValue("");
    }
  }

  return (
    <div>
      <div id="displayPreValue">
        <h4>{preValue}</h4>
      </div>
      <div id="display">
        <h3>{currentValue}</h3>
      </div>
      <section id="number">
        <button id="all cleaer" value="allClear" onClick={handleClick}>
          Ac
        </button>
        <button id="delete">Del</button>
        <button data-number id="one" value="1" onClick={handleClick}>
          1
        </button>
        <button data-number onClick={handleClick} id="two" value="2">
          2
        </button>
        <button data-number id="three" value="3" onClick={handleClick}>
          3
        </button>
        <button data-number id="four" value="4" onClick={handleClick}>
          4
        </button>
        <button data-number id="five" value="5" onClick={handleClick}>
          5
        </button>
        <button data-number id="six" value="6" onClick={handleClick}>
          6
        </button>
        <button data-number id="seven" value="7" onClick={handleClick}>
          7
        </button>
        <button data-number id="eight" value="8" onClick={handleClick}>
          8
        </button>
        <button data-number id="nine" value="9" onClick={handleClick}>
          9
        </button>
        <button data-number id="zero" value="0" onClick={handleClick}>
          0
        </button>
      </section>

      <section id="operator">
        <button data-operator onClick={chooseTheOperator} id="add" value="+">
          +
        </button>
        <button
          data-operator
          id="subtract"
          value="-"
          onClick={chooseTheOperator}
        >
          -
        </button>
        <button
          data-operator
          id="multiply"
          value="X"
          onClick={chooseTheOperator}
        >
          X
        </button>
        <button data-operator id="divide" value="/" onClick={chooseTheOperator}>
          /
        </button>
      </section>

      <section id="other">
        <button id="equals" value="=" onClick={handleClick}>
          {" "}
          ={" "}
        </button>
        <button data-number id="decimal" value="." onClick={handleClick}>
          .
        </button>
        <button id="clear" value="clear" onClick={clearTheNumber}>
          clear
        </button>
      </section>
    </div>
  );
}

export default App;


Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Safari/605.1.15.

Challenge: Build a Markdown Previewer

Link to the challenge:

From the react point of view everything is fine except this line:

Setting state is an async action and therefore you indeed can chain those setState functions, but computation() is sync function that will invoke all your setters again causing so-called promise race condition. At this point literally no one knows whether setCurrentValue(""); from chooseTheOperator function or setCurrentValue(num); from computation function will win, regardless of their position in the code. (because position only matters in sync code).

You need to write your code in a way that will not allow race conditions.

1 Like

… the way to do it is to calculate the final result first and only then set state. Treat setState as if it was a return statement of your function.

let result = preCalculate(a);

if (a === b) {
  result = updateWith(b);
}

if (a === c) {
  result = updateWith(c);
}

setState(result);
1 Like

Thank you so much for helping!! I will study more about this!!