Creating a Simple Calculator in React (Source Code)

Faraz

By Faraz -

Learn how to build a simple calculator app using React.js. Follow our step-by-step tutorial with source code to create your own calculator component.


Creating a Simple Calculator in React (Source Code).jpg

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Preview
  6. Conclusion

Welcome to our comprehensive tutorial on building a simple calculator using React. In this guide, we'll take you through the step-by-step process of creating a basic calculator app with the power of React and JavaScript. Whether you're new to React or looking to sharpen your skills, this tutorial is designed to provide you with a solid foundation in developing web applications with React components.

By the end of this tutorial, you'll have a functional calculator that can handle basic arithmetic operations like addition, subtraction, multiplication, and division. We'll also cover how to style your calculator for a polished and user-friendly appearance.

Are you ready to dive into the world of React development and create something both educational and practical? Let's get started!

Source Code

Step 1 (HTML Code):

To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our calculator.

After creating the files just paste the following codes into your file. Make sure to save your HTML document with a .html extension, so that it can be properly viewed in a web browser.

Let's break down each part:

1. <!DOCTYPE html>: This is the document type declaration, indicating that the document is an HTML5 document.

2. <html lang="en">: This is the opening tag for the HTML document. It sets the document's language to English ("en").

3. <head>: This section contains metadata and resources that are not directly visible on the web page itself. It typically includes elements like <title>, <meta>, and <link>.

  • <title>Calculator in React</title>: This sets the title of the web page to "Calculator in React." The title is displayed in the browser's title bar or tab.
  • <meta charset="UTF-8" />: This specifies the character encoding for the document, which is UTF-8. UTF-8 is a widely used character encoding that supports a wide range of characters from various languages.
  • <meta name="viewport" content="width=device-width" />: This meta tag is often used for responsive web design. It instructs the browser to set the width of the viewport to match the device's width, which helps ensure that the webpage displays correctly on different screen sizes.
  • <link rel="stylesheet" href="styles.css" />: This link tag is used to link an external CSS stylesheet named "styles.css" to the HTML document. The CSS file contains styles to control the appearance of the webpage.

4. <body>: This section contains the actual content of the web page that will be displayed to the user.

  • <div id="wrapper">: This is a <div> element with the id attribute set to "wrapper." It's often used to create a container for other content. In this case, it seems to be a wrapper for the entire content of the webpage.
  • <div id="app"></div>: This is another <div> element with the id attribute set to "app." It appears to be a placeholder for the main content of the web application. React or JavaScript code will populate this <div> with dynamic content.

5. The following <script> tags include references to external JavaScript libraries and a local JavaScript file:

  • react.min.js and react-dom.min.js are versions of the React library.
  • polyfill.number.toLocaleString.js is a polyfill for the toLocaleString method, which provides better internationalization support for number formatting.
  • react-point.min.js another library used in the application.
  • script.js is a local JavaScript file that contains the main logic for the web application. This is where the functionality of the calculator in React is implemented.

This is the basic structure of our calculator using HTML, and now we can move on to styling it using CSS.

Step 2 (CSS Code):

Once the basic HTML structure of the calculator is in place, the next step is to add styling to the calculator using CSS.

Next, we will create our CSS file. In this file, we will use some basic CSS rules to create our calculator. Let's break down the code step by step:

1. html and body Styles:

  • The box-sizing property is set to border-box for the html element. This ensures that padding and border are included in the element's total width and height calculations.
  • The margin and font properties are set to reset default styles for the body element. The margin is set to 0, and the font is set to 'Roboto' with a weight of 100 and a font size of 14 pixels.

2. button Styles:

  • Styles are defined for all button elements on the page.
  • display is set to "block" to make the buttons block-level elements.
  • Various properties like background, border, padding, font-family, user-select, cursor, and outline are modified to create a consistent button appearance and behavior.
  • -webkit-tap-highlight-color is set to make sure there is no tap highlight color on buttons when pressed.

3. button:active Styles:

  • These styles are applied to buttons when they are in the active state (when they are clicked or tapped).
  • A box shadow is added to create a visual feedback effect when a button is pressed.

4. #wrapper and #app Styles:

  • The #wrapper element is defined with a height of 100vh (viewport height) and is set to be a flex container with centered alignment.
  • The #app element has a fixed width and height and is positioned relative to its parent.

5. .calculator Styles:

  • The .calculator class represents a container element for the calculator interface.
  • It has a black background and is set to be a flex container with a column layout.

6. #wrapper .calculator Styles:

  • These styles apply to the .calculator element when it is a descendant of the #wrapper element.
  • A box shadow is added to give it a subtle shadow.

7. .calculator-display and .auto-scaling-text Styles:

  • These styles are applied to elements with the respective classes.
  • .calculator-display sets the appearance of the main display area of the calculator.
  • .auto-scaling-text styles are used to modify text within the calculator display.

8. .calculator-keypad, .calculator .input-keys, .calculator .function-keys, .calculator .digit-keys, and .calculator-key Styles:

  • These styles define the appearance of the calculator keypad and its various components, including input keys, function keys, digit keys, and individual keys within the keypad.
  • Width, height, background, borders, and font sizes are adjusted to create a visually pleasing and functional calculator interface.
  • Special attention is given to the sizing and layout of keys, including adjustments for specific keys like '0' and 'dot'.

9. .calculator .function-keys and .calculator .operator-keys Styles:

  • These styles set the background gradient for function keys and operator keys, respectively, to give them distinct visual styles.

This will give our calculator an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 0;
  font: 100 14px 'Roboto';
}

button {
  display: block;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  user-select: none;
  cursor: pointer;
  outline: none;
  
  -webkit-tap-highlight-color: rgba(0,0,0,0);
}

button:active {
  box-shadow: inset 0px 0px 80px 0px rgba(0,0,0,0.25);
}

#wrapper {
  height: 100vh;
  
  display: flex;
  align-items: center;
  justify-content: center;
}

#app {
  width: 320px;
  height: 520px;
  position: relative;
}

.calculator {
  width: 100%;
  height: 100%;
  background: black;
  
  display: flex;
  flex-direction: column;
}

#wrapper .calculator {
  box-shadow: 0px 0px 20px 0px #aaa;
}

.calculator-display {
  color: white;
  background: #1c191c;
  line-height: 130px;
  font-size: 6em;
  
  flex: 1;
}

.auto-scaling-text {
  display: inline-block;
}

.calculator-display .auto-scaling-text {
  padding: 0 30px;
  position: absolute;
  right: 0;
  transform-origin: right;
}

.calculator-keypad {
  height: 400px;
  
  display: flex;
}

.calculator .input-keys {
  width: 240px;
}

.calculator .function-keys {
  display: flex;
}

.calculator .digit-keys {
  background: #e0e0e7;
  
  display: flex;
  flex-direction: row;
  flex-wrap: wrap-reverse;
}

.calculator-key {
  width: 80px;
  height: 80px;
  border-top: 1px solid #777;
  border-right: 1px solid #666;  
  text-align: center;
  line-height: 80px;
}
.calculator .function-keys .calculator-key {
  font-size: 2em;
}
.calculator .function-keys .key-multiply {
  line-height: 50px;
}
.calculator .digit-keys .calculator-key {
  font-size: 2.25em;
}
.calculator .digit-keys .key-0 {
  width: 160px;
  text-align: left;
  padding-left: 32px;
}
.calculator .digit-keys .key-dot {
  padding-top: 1em;
  font-size: 0.75em;
}
.calculator .operator-keys .calculator-key {
  color: white;
  border-right: 0;
  font-size: 3em;
}

.calculator .function-keys {
  background: linear-gradient(to bottom, rgba(202,202,204,1) 0%, rgba(196,194,204,1) 100%);
}
.calculator .operator-keys {
  background:  linear-gradient(to bottom, rgba(252,156,23,1) 0%, rgba(247,126,27,1) 100%);
} 

Step 3 (JavaScript Code):

Finally, we need to create a function in JavaScript. Let's break down the code step by step:

1. Import React Dependencies: The code starts by importing React and other necessary dependencies.

2. AutoScalingText Component:

  • AutoScalingText is a React component that is used to automatically scale the text within a container based on the available width. It uses a CSS transform property to scale the text.

3. CalculatorDisplay Component:

  • CalculatorDisplay is a React component responsible for rendering the calculator's display area. It formats and displays the numeric value.

4. CalculatorKey Component:

  • CalculatorKey is a React component that represents individual calculator keys (buttons) that users can click on.

5. CalculatorOperations Object:

  • CalculatorOperations is an object that defines mathematical operations (addition, subtraction, multiplication, division) and the corresponding functions to perform these operations.

6. Calculator Component:

  • Calculator is the main React component representing the calculator application.
  • It manages the calculator's state, including the current value, displayed value, operator, and a flag to indicate whether the calculator is waiting for the next operand.
  • The component has methods for handling various calculator operations, such as clearing, inputting digits, performing mathematical operations, and more.
  • It also includes event listeners for keyboard input to control the calculator.
  • The render method returns the JSX for the calculator interface, which includes CalculatorDisplay and a grid of buttons for digits, mathematical operations, and other functions.

7. Event Listeners:

  • The handleKeyDown function is used to handle keyboard events. It maps keyboard keys to calculator functions and updates the state accordingly. This function is attached to the keydown event of the document.
  • Event listeners are set up in the componentDidMount method and removed in the componentWillUnmount method to ensure that keyboard input is properly handled during the component's lifecycle.

8. Rendering:

  • Finally, the code uses ReactDOM.render to render the Calculator component into the HTML element with the ID 'app'. This is where the calculator user interface will be displayed on the web page.

Create a JavaScript file with the name script.js and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.

const PointTarget = ReactPoint.PointTarget

class AutoScalingText extends React.Component {
  state = {
    scale: 1
  };
  
  componentDidUpdate() {
    const { scale } = this.state
    
    const node = this.node
    const parentNode = node.parentNode
    
    const availableWidth = parentNode.offsetWidth
    const actualWidth = node.offsetWidth
    const actualScale = availableWidth / actualWidth
    
    if (scale === actualScale)
      return
    
    if (actualScale < 1) {
      this.setState({ scale: actualScale })
    } else if (scale < 1) {
      this.setState({ scale: 1 })
    }
  }
  
  render() {
    const { scale } = this.state
    
    return (
      <div
        className="auto-scaling-text"
        style={{ transform: `scale(${scale},${scale})` }}
        ref={node => this.node = node}
      >{this.props.children}</div>
    )
  }
}

class CalculatorDisplay extends React.Component {
  render() {
    const { value, ...props } = this.props
    
    const language = navigator.language || 'en-US'
    let formattedValue = parseFloat(value).toLocaleString(language, {
      useGrouping: true,
      maximumFractionDigits: 6
    })
    
    // Add back missing .0 in e.g. 12.0
    const match = value.match(/\.\d*?(0*)$/)
    
    if (match)
      formattedValue += (/[1-9]/).test(match[0]) ? match[1] : match[0]
    
    return (
      <div {...props} className="calculator-display">
        <AutoScalingText>{formattedValue}</AutoScalingText>
      </div>
    )
  }
}

class CalculatorKey extends React.Component {
  render() {
    const { onPress, className, ...props } = this.props
    
    return (
      <PointTarget onPoint={onPress}>
        <button className={`calculator-key ${className}`} {...props}/>
      </PointTarget>
    )
  }
}

const CalculatorOperations = {
  '/': (prevValue, nextValue) => prevValue / nextValue,
  '*': (prevValue, nextValue) => prevValue * nextValue,
  '+': (prevValue, nextValue) => prevValue + nextValue,
  '-': (prevValue, nextValue) => prevValue - nextValue,
  '=': (prevValue, nextValue) => nextValue
}

class Calculator extends React.Component {
  state = {
    value: null,
    displayValue: '0',
    operator: null,
    waitingForOperand: false
  };
  
  clearAll() {
    this.setState({
      value: null,
      displayValue: '0',
      operator: null,
      waitingForOperand: false
    })
  }

  clearDisplay() {
    this.setState({
      displayValue: '0'
    })
  }
  
  clearLastChar() {
    const { displayValue } = this.state
    
    this.setState({
      displayValue: displayValue.substring(0, displayValue.length - 1) || '0'
    })
  }
  
  toggleSign() {
    const { displayValue } = this.state
    const newValue = parseFloat(displayValue) * -1
    
    this.setState({
      displayValue: String(newValue)
    })
  }
  
  inputPercent() {
    const { displayValue } = this.state
    const currentValue = parseFloat(displayValue)
    
    if (currentValue === 0)
      return
    
    const fixedDigits = displayValue.replace(/^-?\d*\.?/, '')
    const newValue = parseFloat(displayValue) / 100
    
    this.setState({
      displayValue: String(newValue.toFixed(fixedDigits.length + 2))
    })
  }
  
  inputDot() {
    const { displayValue } = this.state
    
    if (!(/\./).test(displayValue)) {
      this.setState({
        displayValue: displayValue + '.',
        waitingForOperand: false
      })
    }
  }
  
  inputDigit(digit) {
    const { displayValue, waitingForOperand } = this.state
    
    if (waitingForOperand) {
      this.setState({
        displayValue: String(digit),
        waitingForOperand: false
      })
    } else {
      this.setState({
        displayValue: displayValue === '0' ? String(digit) : displayValue + digit
      })
    }
  }
  
  performOperation(nextOperator) {    
    const { value, displayValue, operator } = this.state
    const inputValue = parseFloat(displayValue)
    
    if (value == null) {
      this.setState({
        value: inputValue
      })
    } else if (operator) {
      const currentValue = value || 0
      const newValue = CalculatorOperations[operator](currentValue, inputValue)
      
      this.setState({
        value: newValue,
        displayValue: String(newValue)
      })
    }
    
    this.setState({
      waitingForOperand: true,
      operator: nextOperator
    })
  }
  
  handleKeyDown = (event) => {
    let { key } = event
    
    if (key === 'Enter')
      key = '='
    
    if ((/\d/).test(key)) {
      event.preventDefault()
      this.inputDigit(parseInt(key, 10))
    } else if (key in CalculatorOperations) {
      event.preventDefault()
      this.performOperation(key)
    } else if (key === '.') {
      event.preventDefault()
      this.inputDot()
    } else if (key === '%') {
      event.preventDefault()
      this.inputPercent()
    } else if (key === 'Backspace') {
      event.preventDefault()
      this.clearLastChar()
    } else if (key === 'Clear') {
      event.preventDefault()
      
      if (this.state.displayValue !== '0') {
        this.clearDisplay()
      } else {
        this.clearAll()
      }
    }
  };
  
  componentDidMount() {
    document.addEventListener('keydown', this.handleKeyDown)
  }
  
  componentWillUnmount() {
    document.removeEventListener('keydown', this.handleKeyDown)
  }
  
  render() {
    const { displayValue } = this.state
    
    const clearDisplay = displayValue !== '0'
    const clearText = clearDisplay ? 'C' : 'AC'
    
    return (
      <div className="calculator">
        <CalculatorDisplay value={displayValue}/>
        <div className="calculator-keypad">
          <div className="input-keys">
            <div className="function-keys">
              <CalculatorKey className="key-clear" onPress={() => clearDisplay ? this.clearDisplay() : this.clearAll()}>{clearText}</CalculatorKey>
              <CalculatorKey className="key-sign" onPress={() => this.toggleSign()}>±</CalculatorKey>
              <CalculatorKey className="key-percent" onPress={() => this.inputPercent()}>%</CalculatorKey>
            </div>
            <div className="digit-keys">
              <CalculatorKey className="key-0" onPress={() => this.inputDigit(0)}>0</CalculatorKey>
              <CalculatorKey className="key-dot" onPress={() => this.inputDot()}>●</CalculatorKey>
              <CalculatorKey className="key-1" onPress={() => this.inputDigit(1)}>1</CalculatorKey>
              <CalculatorKey className="key-2" onPress={() => this.inputDigit(2)}>2</CalculatorKey>
              <CalculatorKey className="key-3" onPress={() => this.inputDigit(3)}>3</CalculatorKey>
              <CalculatorKey className="key-4" onPress={() => this.inputDigit(4)}>4</CalculatorKey>
              <CalculatorKey className="key-5" onPress={() => this.inputDigit(5)}>5</CalculatorKey>
              <CalculatorKey className="key-6" onPress={() => this.inputDigit(6)}>6</CalculatorKey>
              <CalculatorKey className="key-7" onPress={() => this.inputDigit(7)}>7</CalculatorKey>
              <CalculatorKey className="key-8" onPress={() => this.inputDigit(8)}>8</CalculatorKey>
              <CalculatorKey className="key-9" onPress={() => this.inputDigit(9)}>9</CalculatorKey>
            </div>
          </div>
          <div className="operator-keys">
            <CalculatorKey className="key-divide" onPress={() => this.performOperation('/')}>÷</CalculatorKey>
            <CalculatorKey className="key-multiply" onPress={() => this.performOperation('*')}>×</CalculatorKey>
            <CalculatorKey className="key-subtract" onPress={() => this.performOperation('-')}>−</CalculatorKey>
            <CalculatorKey className="key-add" onPress={() => this.performOperation('+')}>+</CalculatorKey>
            <CalculatorKey className="key-equals" onPress={() => this.performOperation('=')}>=</CalculatorKey>
          </div>
        </div>
      </div>
    )
  }
}

ReactDOM.render(
  <Calculator/>,
  document.getElementById('app')
)

Final Output:

Creating a Simple Calculator in React (Source Code).gif

Conclusion:

Congratulations! You've successfully completed our journey to build a simple calculator using React. Throughout this tutorial, you've gained valuable insights into React components, state management, user input handling, and basic arithmetic operations. You've also learned how to style your calculator for a visually appealing user interface.

As you continue your journey in React development, remember that this simple calculator is just the beginning. You can expand and enhance it with advanced features like memory functions, scientific calculations, or complex expressions.

We encourage you to explore further, experiment with new ideas, and continue learning. React offers a world of possibilities for building dynamic web applications, and your newfound skills will serve as a strong foundation for your future projects.

Thank you for joining us on this educational coding adventure. We hope you found this tutorial both informative and enjoyable. Happy coding, and best of luck with your React development endeavors!

Code by: Michael Jackson

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post