Simple Calculator is the best way to build a good understanding of react concepts. Let me know if there is any best way in which the same code can be implemented
So please do comment on what you think.
Following are the links to source code:
GitHub: https://github.com/akshayrak/react-simpl-calculator1234.git
StackBlitz: https://stackblitz.com/edit/react-simpl-calculator1234?file=src/App.js
Application link: https://react-simpl-calculator1234.stackblitz.io
I have started it by creating a simple form
<form>
<input
type="text"
onChange={e => setInput(e.target.value)}
value={input}
/>
</form>
we can use useState hook to maintain the state of the form
const [input, setInput] = useState("0")
Default value will be zero
For the buttons we can create a variable and put all the symbols in an array
const symbols = [
'c',
'<-',
'%',
'/',
'7',
'8',
'9',
'X',
'4',
'5',
'6',
'-',
'1',
'2',
'3',
'+',
'.',
'0',
'='
];
so now we can use 'map' method in js to loop through all the elements and return a array of button elements
<div>
{symbols.map((symbol, i) => (
<button key={i} onClick={()=>handleSymbol(symbol)}>
{symbol}
</button>
))}
</div>
At this point it should look somewhat like this
This is all the UI we want, now we can implement the logic for calculations.
whenever a button is clicked "handleSymbol" method is triggered and the respective "symbol" is passed as an argument. Now we need to check what that symbol is and what should we do with it.
So here I am using "input" state for maintaining the state of the form and also displaying the result in the same TextField. so we just need to set the final answer to "input".
Now to get the answer we need to do few checks,
check1: whether to Concatenate or to backspace or to delete or to calculate
This can be done simply using if else statements
if (symbol != 'c' && symbol != '<-' && symbol != '=') {
//concatenate
}else if(symbol == 'c') {
//delete
} else if (symbol == '<-' && input != '0'&&input!='') {
//backspace
} else if (symbol == '=') {
//calculate
}
if it is Concatenate than we need to check what it is
if (symbol == '.') {
let temp = input.match(/[\d\.]+|\D+/g);//separate the string and the integer
temp==null?temp=["0"]:null //sets 0 if temp is null
//checks whether dot exists or not in the last element (we can't have two dots in the same number)
if (!temp[temp.length - 1].includes('.')) {
//checks whether dot is typed after a symbol
if (temp[temp.length - 1] == '+' ||
temp[temp.length - 1] == '-' ||
temp[temp.length - 1] == 'X' ||
temp[temp.length - 1] == '/' ||
temp[temp.length - 1] == '%') {
//if it is typed after a symbol than it adds '0.' (so that it looks like a number)
setInput(prev => prev + '0.')
}
else {
setInput(prev => prev + symbol)
}
}
}
if its not a don't and if its some thing else than
else{
let temp = input.match(/[^\d]+|\d+/g);//separate the string and the integer
temp==null?temp=["0"]:null //sets 0 if temp is null
//these two if blocks checks whether the previously typed and current typed are operators (you can't put two operators next to each other)
if (
temp[temp.length - 1] == '+' ||
temp[temp.length - 1] == '-' ||
temp[temp.length - 1] == 'X' ||
temp[temp.length - 1] == '/' ||
temp[temp.length - 1] == '%'
) {
//checks whether its a symbol or number
if (
symbol == '+' ||
symbol == '-' ||
symbol == 'X' ||
symbol == '/' ||
symbol == '%'
) {
//if symbol than remove the previous one and concatenate the new one
setInput(prev => prev.slice(0, -1));
setInput(prev => prev + symbol);
} else {
//if number than concatenate
setInput(prev => prev + symbol);
}
} else {
//if previous one is a number than concatenate the current one too
setInput(prev => prev + symbol);
}
}
now if its a backspace or a delete than its simple
else if (symbol == 'c') {
setInput('0');
} else if (symbol == '<-' && input != '0'&&input!='') {
setInput(prev => prev.slice(0, -1));
}
if its an equals symbol than we need to calculate
else if (symbol == '=') {
let temp = input.match(/[^\d]+|\d+/g);//separate the string and the integer
temp==null?temp=["0"]:null //sets 0 if temp is null
//checks if the late typed character is a operator
if (
temp[temp.length - 1] == '+' ||
temp[temp.length - 1] == '-' ||
temp[temp.length - 1] == '/' ||
temp[temp.length - 1] == 'X'
) {
//if its a operator than remove
temp.pop();
}
//Now we are using simple BODMAS rule to calculate
//if % exists than divide the number by 100 and multiply with the following number
while (temp.includes('%')) {
const index = temp.indexOf('%');
const num1 = parseFloat(temp[index - 1]);
let tempResult = (num1 / 100).toFixed(2).toString();
temp.splice(index, 1, 'X');
temp.splice(index - 1, 1, tempResult);
}
//if '/' exists than divide the two numbers and remove them and replace the result
while (temp.includes('/')) {
const index = temp.indexOf('/');
const num1 = parseFloat(temp[index - 1]);
const num2 = parseFloat(temp[index + 1]);
const tempResult = (num1 / num2).toFixed(2).toString();
temp.splice(index, 1);
temp.splice(index, 1);
temp.splice(index - 1, 1, tempResult);
}
//if 'X' exists than multiply the two numbers and remove them and replace the result
while (temp.includes('X')) {
const index = temp.indexOf('X');
const num1 = parseFloat(temp[index - 1]);
const num2 = parseFloat(temp[index + 1]);
let tempResult = (num1 * num2).toFixed(2).toString();
temp.splice(index, 1);
temp.splice(index, 1);
temp.splice(index - 1, 1, tempResult);
}
//if '+' exists than add the two numbers and remove them and replace the result
while (temp.includes('+')) {
const index = temp.indexOf('+');
const num1 = parseFloat(temp[index - 1]);
const num2 = parseFloat(temp[index + 1]);
let tempResult = (num1 + num2).toFixed(2).toString();
temp.splice(index, 1);
temp.splice(index, 1);
temp.splice(index - 1, 1, tempResult);
}
//if '-' exists than subtract the two numbers and remove them and replace the result
while (temp.includes('-')) {
const index = temp.indexOf('-');
const num1 = parseFloat(temp[index - 1]);
const num2 = parseFloat(temp[index + 1]);
let tempResult = (num1 - num2).toFixed(2).toString();
temp.splice(index, 1);
temp.splice(index, 1);
temp.splice(index - 1, 1, tempResult);
}
//result can be set to input so that we can show it in the same textBox in which we type
setInput(temp[0]);
}
I have included most of the explanation as comments, so in case if you don't understand let me know.
And if you can make it better let me know as well.
Thanks
Akshay
Top comments (0)