Click files to view code →
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
Use React's
useState[!IMPORTANT] Requirements
No external dependencies needed.
Key Topics:
Plan of Action:
Calculatorimport 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):
.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;
}
// ...Best Practices:
Common Pitfalls:
Enhancements:
Advanced Version with History:
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:
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:
Real-World Use Cases:
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