Calculator

intermediate
40 min

Explorer

1
⚛️
Calculator.jsx

Click files to view code →

React Simple Calculator Component Tutorial

1. What is the Question and What to Achieve Here

Build a functional calculator component that performs basic arithmetic operations (addition, subtraction, multiplication, division). The calculator should have a display showing the current value and buttons for numbers and operations.

[!TIP] Goal

  • Display current value and operation
  • Handle number input (0-9)
  • Perform basic operations (+, -, ×, ÷)
  • Clear display and reset calculator
  • Handle decimal numbers
  • Show calculation results
  • Prevent invalid operations (divide by zero, etc.)

2. How to Solve

Use React's

text
useState
hook to manage calculator state including current display value, previous value, and the selected operation. Process button clicks to update state and perform calculations when equals is pressed.

3. What Are the Things That Need to Be Gathered

[!IMPORTANT] Requirements

  • React with hooks
  • Understanding of:
    • State management for multiple values
    • Mathematical operations
    • String/number conversions
    • Event handling
    • Grid layout with CSS

No external dependencies needed.

4. Key Topics to Consider and Plan of Action

Key Topics:

  • State Management: Tracking display, previous value, operation, and flags
  • Operation Logic: Handling sequential operations
  • Decimal Handling: Preventing multiple decimal points
  • Edge Cases: Division by zero, consecutive operations
  • Display Formatting: Number formatting and overflow handling
  • Clear vs All Clear: Difference between C and AC buttons

Plan of Action:

  1. Create
    text
    Calculator
    component
  2. Initialize state for display, previous value, operation, and waiting flag
  3. Create handler for number buttons
  4. Create handler for operation buttons
  5. Create handler for equals button
  6. Create handler for clear button
  7. Design calculator grid layout with CSS
  8. Handle decimal point button
  9. Add error handling for edge cases

5. Code the Question

jsxShowing 50 of 145 lines
import React, { useState } from 'react';
import './Calculator.css';

function Calculator() {
  const [display, setDisplay] = useState('0');
  const [previousValue, setPreviousValue] = useState(null);
  const [operation, setOperation] = useState(null);
  const [waitingForOperand, setWaitingForOperand] = useState(false);

  // Handle number button clicks
  const inputNumber = (num) => {
    if (waitingForOperand) {
      setDisplay(String(num));
      setWaitingForOperand(false);
    } else {
      setDisplay(display === '0' ? String(num) : display + num);
    }
  };

  // Handle decimal point
  const inputDecimal = () => {
    if (waitingForOperand) {
      setDisplay('0.');
      setWaitingForOperand(false);
    } else if (display.indexOf('.') === -1) {
      setDisplay(display + '.');
    }
  };

  // Clear display
  const clear = () => {
    setDisplay('0');
  };

  // All clear - reset everything
  const allClear = () => {
    setDisplay('0');
    setPreviousValue(null);
    setOperation(null);
    setWaitingForOperand(false);
  };

  // Perform calculation
  const performOperation = (nextOperation) => {
    const inputValue = parseFloat(display);

    if (previousValue === null) {
      setPreviousValue(inputValue);
    } else if (operation) {
      const currentValue = previousValue || 0;
// ...

CSS Styling (Calculator.css):

cssShowing 50 of 98 lines
.calculator {
  width: 320px;
  margin: 2rem auto;
  padding: 1rem;
  background: linear-gradient(145deg, #2c2c2c, #1a1a1a);
  border-radius: 20px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
  font-family: 'Arial', sans-serif;
}

.calculator-display {
  background-color: #1a1a1a;
  color: #fff;
  font-size: 3rem;
  text-align: right;
  padding: 1.5rem 1rem;
  border-radius: 10px;
  margin-bottom: 1rem;
  min-height: 80px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  overflow: hidden;
  word-wrap: break-word;
  font-weight: 300;
}

.calculator-keypad {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.calculator-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
}

button {
  padding: 1.25rem;
  font-size: 1.5rem;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.2s ease;
  outline: none;
}

// ...

6. Things to Consider

Best Practices:

  • State Management: Keep track of current value, previous value, operation, and waiting state
  • Floating Point Precision: Handle JavaScript floating point arithmetic issues
  • User Feedback: Provide visual feedback for button presses
  • Error Handling: Handle division by zero and invalid operations
  • Display Overflow: Limit display length or use scientific notation
  • Keyboard Support: Add keyboard input handling

Common Pitfalls:

  • Don't forget to handle consecutive operations without pressing equals
  • Be careful with floating point arithmetic (0.1 + 0.2 !== 0.3 in JavaScript)
  • Handle edge case of pressing equals multiple times
  • Don't allow multiple decimal points
  • Remember to reset waiting state appropriately

Enhancements:

  • Memory Functions: M+, M-, MR, MC buttons
  • History: Show calculation history
  • Keyboard Input: Support keyboard number and operation keys
  • Scientific Mode: Add advanced operations (sin, cos, sqrt, etc.)
  • Themes: Multiple color themes
  • Sound Effects: Button click sounds
  • Responsive Design: Adapt to different screen sizes
  • Copy to Clipboard: Copy result functionality

Advanced Version with History:

jsx
import React, { useState } from 'react';

function CalculatorWithHistory() {
  const [display, setDisplay] = useState('0');
  const [history, setHistory] = useState([]);
  // ... other state

  const handleEquals = () => {
    const inputValue = parseFloat(display);

    if (previousValue !== null && operation) {
      const result = calculate(previousValue, inputValue, operation);
      
      // Add to history
      const calculation = `${previousValue} ${operation} ${inputValue} = ${result}`;
      setHistory([calculation, ...history]);
      
      setDisplay(String(result));
      setPreviousValue(null);
      setOperation(null);
      setWaitingForOperand(true);
    }
  };

  return (
    <div className="calculator-container">
      <div className="calculator">
        {/* Calculator UI */}
      </div>
      
      <div className="history-panel">
        <h3>History</h3>
        {history.map((item, index) => (
          <div key={index} className="history-item">
            {item}
          </div>
        ))}
      </div>
    </div>
  );
}

Keyboard Support:

jsx
import React, { useState, useEffect } from 'react';

function Calculator() {
  // ... existing state

  useEffect(() => {
    const handleKeyPress = (e) => {
      if (e.key >= '0' && e.key <= '9') {
        inputNumber(parseInt(e.key));
      } else if (e.key === '.') {
        inputDecimal();
      } else if (e.key === '+' || e.key === '-' || e.key === '*' || e.key === '/') {
        const opMap = { '+': '+', '-': '-', '*': '×', '/': '÷' };
        performOperation(opMap[e.key]);
      } else if (e.key === 'Enter' || e.key === '=') {
        handleEquals();
      } else if (e.key === 'Escape') {
        allClear();
      }
    };

    window.addEventListener('keydown', handleKeyPress);
    return () => window.removeEventListener('keydown', handleKeyPress);
  }, [display, previousValue, operation, waitingForOperand]);

  // ... rest of component
}

Testing Considerations:

  • Test basic operations (1 + 1 = 2)
  • Test chained operations (2 + 3 + 4 = 9)
  • Test decimal operations (0.1 + 0.2)
  • Test division by zero
  • Test negative numbers
  • Test clearing and resetting
  • Test edge cases (very large numbers, very small numbers)
  • Test rapid button clicking

Real-World Use Cases:

  • Basic calculator applications
  • Shopping cart totals
  • Tip calculators
  • Financial calculators
  • Educational math tools
  • Unit conversion calculators

This calculator component demonstrates complex state management and serves as a foundation for more advanced calculator applications.

No files open

Click a file in the explorer to view