JavaScript Calculator

I have encountered a problem. I am trying to display the numbers being pressed, but when I first press a button, the number doesn’t show up at first, but when I press another button, the first initial number that I pressed shows up but the recent number doesn’t. This goes on with every button I press.

For example, I press one, it doesn’t display. I press two, one displays but two doesn’t. I press three and it doesn’t display, but one and two do. Please help.

JavaScript code

import React from "react";
import './styles.scss';

const calcGridOne = [
    {
        btnName: "AC",
        btnId: "clear"
    },
    {
        btnName: "+",
        btnId: "add"
    }
];
const calcGridTwo = [
    {
        btnName: "1",
        btnId: "one"
    },
    {
        btnName: "2",
        btnId: "two"
    },
    {
        btnName: "3",
        btnId: "three"
    },
    {
        btnName: "-",
        btnId: "subtract"
    },
    {
        btnName: "4",
        btnId: "four"
    },
    {
        btnName: "5",
        btnId: "five"
    },
    {
        btnName: "6",
        btnId: "six"
    },
    {
        btnName: "x",
        btnId: "multiply"
    },
    {
        btnName: "7",
        btnId: "seven"
    },
    {
        btnName: "8",
        btnId: "eight"
    },
    {
        btnName: "9",
        btnId: "nine"
    },
    {
        btnName: "/",
        btnId: "divide"
    }
]

const calcGridThree = [
    {
        btnName: "0",
        btnId: "zero"
    },
    {
        btnName: ".",
        btnId: "decimal"
    },
    {
        btnName: "=",
        btnId: "equals"
    }
];

class Calculator extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            display: "0",
            equationArr: [],
            numArr: [],
            equation: ""
        }
        this.handleInput = this.handleInput.bind(this);
        this.setDisplay = this.setDisplay.bind(this);
    }    

    //Handles the buttons pressed by user
    handleInput(input){
        // if(this.state.display === "0" && input === "."){
        //     this.setState({
        //         display: "0."
        //     })
        // }

        // console.log("equationArr before: ", this.state.equationArr);

        this.setState((prevState)=>({
            equationArr:[...prevState.equationArr, input]
        }))
        this.setState({
            display: this.state.equationArr.join("")
        });
        // console.log("equationArr after: ", this.state.equationArr);

        // console.log("------------------");
        // console.log("handleInput method");
        // console.log("display: ", this.state.display);
        // console.log("------------------");
    }

    setDisplay(){

    }

    render(){
        return (
            <div className="calc-container">
                <p>TEST 2 TEST 2 TEST 3</p>

                <div id="display">{this.state.display}</div>

                <div className="grid-container-1">
                    {calcGridOne.map((el)=>(
                        <div id={el.btnId} onClick={()=>{this.handleInput(el.btnName)}}>{el.btnName}</div>
                    ))}
                </div>

                <div className="grid-container-2">
                    {calcGridTwo.map((el)=>(
                        <div id={el.btnId} onClick={()=>{this.handleInput(el.btnName)}}>{el.btnName}</div>
                    ))}
                </div>
                
                <div className="grid-container-3">
                    {calcGridThree.map((el)=>(
                        <div id={el.btnId} onClick={()=>{this.handleInput(el.btnName)}}>{el.btnName}</div>
                    ))}
                </div>
            </div>
        );
    }
}

export default Calculator;

The second state setter depends on the first, and it won’t have access to the updated state value until the next render.

The setState second argument callback will give you access to it.

this.setState(
  (prevState) => ({
    equationArr: [...prevState.equationArr, input],
  }),
  () => {
    this.setState({
      display: this.state.equationArr.join(''),
    });
  }
);

However, you likely do not need a state variable for the display if all you are doing is rendering the this.state.equationArr.join('') value. You could just put it inside the render method.

render() {
  const derivedInput = this.state.equationArr.join('');
  return (
    // other component code
	<div id="display">{derivedInput}</div>
	// other component code
	)
}

As an aside, remember to put keys on your mapped elements.

1 Like