State for the second number
→ Click here to see the state of the app after completing this step.
→ Click here to see the changes we'll make in this step in GitHub.
After choosing an arithmetic operator, the user has to enter a second number for the calculation.
We'll start like we did for the operator: Add some new state, show it in the calculator display, add a set-state-handler that does nothing yet and attach it to the onclick event of the button elements.
3const firstNumber = gg.state(""); 4const operator = gg.state("");+5const secondNumber = gg.state(""); ⋮ 48 +49const setSecondNumber = gg.setState(secondNumber, (value) => {+50 return value;+51});+52 53const buttonStyles = gg.stylesheet(` ⋮ 96 return (-<button class={classes} onclick={[setFirstNumber, setOperator]}>+97 <button+98 class={classes}+99 onclick={[setFirstNumber, setOperator, setSecondNumber]}+100 > 101 {args.children} 102 </button> 103 ); ⋮ 137 <div class={[stylesheet.getClass("display")]}>-{firstNumber} {operator}+138 {firstNumber} {operator} {secondNumber} 139 </div>
The state of the second number depends again on the state of the operator. We only want to change the state of the second number if there already is an operator. Otherwise the user is still entering the first number.
48 -const setSecondNumber = gg.setState(secondNumber, (value) => {-return value;-});+49const setSecondNumber = gg.setState(+50 secondNumber,+51 (value, event, [operatorValue]) => {+52 if (!operatorValue) {+53 return value;+54 }+55 return value;+56 },+57 [operator],+58); 59
We can also do the same thing as for the other two state again to find out which button has been clicked.
52 if (!operatorValue) { 53 return value; 54 }+55 if (!(event.target instanceof HTMLButtonElement)) {+56 return value;+57 }+58 const buttonText = event.target.innerText; 59 return value;
The logic of updating the state is then the same as for the first number.
58 const buttonText = event.target.innerText;+59 if (["1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(buttonText)) {+60 return value + buttonText;+61 }+62 if (buttonText === "0" && value) {+63 return value + buttonText;+64 }+65 if (buttonText === "." && !value.includes(".")) {+66 return value + buttonText;+67 } 68 return value;
Now there is one more thing we need to take care of. Once the user started entering the second number, we won't him change the operator again. So let's add another state dependency for the operator state.
31const setOperator = gg.setState( 32 operator,-(value, event, [firstNumberValue]) => {+33 (value, event, [firstNumberValue, secondNumberValue]) => { 34 if (!firstNumberValue || firstNumberValue === ".") { 35 return value; 36 }+37 if (secondNumberValue) {+38 return value;+39 } 40 if (!(event.target instanceof HTMLButtonElement)) { 41 return value; 42 } 43 const buttonText = event.target.innerText; 44 if (["+", "-", "×", "÷"].includes(buttonText)) { 45 return buttonText; 46 } 47 return value; 48 },-[firstNumber],+49 [firstNumber, secondNumber], 50);
That should already be it. Now the user can enter two numbers and an operator, all that is left is calculating the result and adding the functionality for the control buttons.
However, before we do that, let's take a step back and look at all the state we added so far and see how we can improve further on the code.
Next → Combining multiple states