React Calculator Test 13 Solution

Hey everyone- I am wrapping up a rough draft of my React Calculator and I am failing the consecutive operator test…

I wrote my code such that you cant enter consecutive operators, it just will ignore the click event if you try to enter a second operator without first hitting another number. This seems more elegant than parsing whatever is entered. Would there be a way to get credit for completing this project if everything else checks out?

A snipnet of the code that controls this logic:

    const handleOperator = (operator) => {
        // only allow an operator to be entered if a number has been entered
        if(this.state.result !== 0 && this.state.operator === false){ 
            this.setState(prevState => ({ result: prevState.result + operator }));
            this.setState({ operator: true });
        }
    };

const handleClick = (event) => {
      // console.log(`clicked ${event.display}`);
      const { display, id } = event;
      switch (id){
          case 'clear':
              // reset display
              clearDisplay();
              break;
          case 'divide':
          case 'multiply':
          case 'add':
          case 'subtract':
              // insert the correct operator into calculator expression
              const operator = display;
              handleOperator(operator);
              this.setState({ decimal: false });
              break;
          case 'decimal':
              // handle decimals
              if(this.state.decimal === false){
                  this.setState(prevState => ({ result: prevState.result + display }));
                  this.setState({ decimal:true });
              }
              break;
          case 'equals':
              // handle solving input
              const result = calculateResult();
              console.log(String(result));
              this.setState({result:result});
              break;
          default:
              // handle number input
              // if display has "0", rewrite initial number
              if (this.state.result == 0) { 
                this.setState({ result: display });
              } else {
                this.setState(prevState => ({ result: prevState.result + display }));
                this.setState({ operator:false });
              }
      }

My full code is on github

A running preview can also been seen here

Well, the problem is that your solution is in direct conflict with User Story 13, as you’ve noted:

  • User Story #13: If 2 or more operators are entered consecutively, the operation performed should be the last operator entered.

So, in the event of multiple operators, the test is looking for the LAST operator to be the only one that runs – you are trying to make it be the FIRST.

Perhaps, rather than checking if the state.operator is true, you can simply check the last character of state.result to see whether it’s an operator and replace that.

Or the other option is, create an “operations stack”: when the operator is clicked, push the number previous onto the stack, then push the operator. Doing that, given a second operator, you’d simply replace the existing operator on the end of that stack (stack, in this case, being an array).

I understand what it wants to accomplish, I’m trying to say that entering consecutive operators isn’t a possibility the way I set the logic up. It wont let you enter “1 - + 2”, so handling that is a moot point. I personally like that better and wanted to see if it could still be validated as a complete project.

In an effort to trying to implement it working as originally described, I forked my github and currently have the following changes to my solving function. I get the corrected expression console logged out but my state is showing as undefined…any thoughts?

const calculateResult = () => {
      const expression = this.state.result.split('');
      const operatorRegex = /[+\-\/*]/; /* eslint no-useless-escape:0 */
      console.log(expression);
      const removed = [];
      for (let i = 0; i < expression.length; i++) {
        // check if letter is an operator
        if (operatorRegex.test(expression[i])) {
          // if character is an operator, check if the next character is a operator
          // if it is, remove the first operator and reset to beginning to loop
          if (operatorRegex.test(expression[i + 1])) {
            expression.splice(i, 1);
            i = 0;
          } else {
            break;
          }
        }
        removed.push(expression[i]);
      }
      const fixed = expression.join('');
      console.log(`updated expression: ${fixed}`);
      this.setState({ result: fixed });

    //   const result = math.eval(expression);
    //   console.log(`result: ${result}`);
    //   return result;
    };

A test case of “1 */-+1” logs “1+1”, but the state isn’t getting set right

Well I dont quite know why, but I just passed my fixed constant into math.eval() and that evaluated correctly, and would setState correctly… so all tests pass now :slight_smile:

Any ideas as to why using setState({result:fixed}) returns undefined though?