Calculator Trouble (React)

Hi everybody

So, trying to do the calculator project with React, and I have one main question and one bug I can’t resolve, would love your feedback.

First, the question - I went with “formulaic logic” by using eval() to do the actual calculation. I saw that even the FCC example calculator does that, even though it’s recommended in the docs to avoid eval().

I suppose it is possible to do an immediate-logic calculator, but in React, wouldn’t that involve saving way too much states (you would need, at the very least, one for the saved number (or current result), and one for the current operator. I also have a state for whether a number already has a decimal in it.
Wouldn’t it get really messy real quick? Is that the learning point of this exercise?

And, for my bug, it’s with test 13 (two or more operators). I got a few lines of codes going that are supposed to correct this, but for some reason, the rendered display becomes a number rather than a string (despite my many attempt to toString() it), and then I get an exception on the second calculation.

Here are the relevant lines:

// if last char in display is operator 
// if (isOperator(display.charAt(display.length - 1)) && op !== "-") {
//   const updatedDisplayStr = display.slice(0, display.length - 1)
//     .concat(op);
//   setDisplay(updatedDisplayStr);
// };

The problem is that “display.charAt is not a funciton”, since for some reason, display (the variable in state) becomes a number, despite my attempts to toString() it.

And these are found in the handleOperator function (a designated function to handle operations).

The full code is here:

Would love any input on this. Calculators aren’t as simple as they seem to be!

Thanks!

You can wrap display inside a call to String()

String(display).charAt(display.length - 1)

But that won’t fix the last test. Pretty sure for the test input 5 * - + 5 your logic will keep the * if the next operator is a - (so it becomes 25 and not 10).

You likely also have to switch the order of the condition and the state setter and return out of the handleOperator function inside the condition at the end. You can’t rely on the state right after you set it, that type of synchronization is usually done inside a useEffect. But in this case, I think simply switching the order and having a return should work. None of this will fix the logic issue though.

Edit: Oh and the isOperator function definition should be moved out of the handleOperator definition. I don’t think there is a good reason to have it nested. It is a stand-alone utility function.

Hey @lasjorg and everyone else, I’ve tried some other approach, still with problems:

So, in my never-yet-ending journey to build a calculator in React, I’m trying all sorts of different things, but I think I’m either missing something very basic about how React works, or I’m actually close to the mark, but there’s some bug I’m not seeing.

My first attempt was to use eval() to do a formulaic-calculation calculator. I even saw that the “official” FCC calculator uses eval. However, the documentation highlights “Don’t use eval()” in big bright letters, and also I wanted to do a “manual” calculation to understand the process better.

So, in my second attempt - link to to incomplete project here - I am trying an immediate-calculation logic, without using eval(). To do that, I need to successfully extract the two operands, as well as the operator, in every operation.

So, I have a state that saves the current (ie last relevant) operator, and I have a state to save the “first number” (which also serves as the result of the previous calculation), and I try to extract the second number using parseFloat() from the display (which is a string), using slice.

The current result is that I’m getting weird results, incorrect ones, and it’s become very unclear to me how they are even calculated. Is it because React is rendering too many times whenever an operator is clicked (and so the display is changing)?
The relevant function is this: (though I need to check my “handleClear” function as well:

function handleOperator(op) {
setHasDecimal(false);

if (!operator) {
setFirstNumber(parseFloat(display));
setOperator(op);
setDisplay((prev) => prev.concat(op));
return;

//TRYING TO PARSE SECOND NUMBER FROM HERE
const second = parseFloat(display.slice(display.indexOf(op) + 1));
const second = parseFloat(display.slice(display.indexOf(op) + 1));
const result = calculate(firstNumber, operator, second) .toString().concat(op);
setFirstNumber(result);
setDisplay(result.toString().concat(op));
setOperator(op);
setOperator(op);
}

Essentially, I’m trying to (1) extract the second number from the display, then (2) use the existing first number, (3) use the existing operator, (4) send to a calculating function, (5), re-save the result as the first number, and (6) save the newly-clicked operator in state (overriding the old one). Somewhere things get lost.

Also, are there too many states already? Is this getting too complex already?

I’d love any feedback on this.
Thank you!