I have made simple calculator in React JS. All the functions are working fine but i need to implement these two functionalities whom i am facing trouble with :
1) When operator(+ or -)is clicked, after that, if again an operator is clicked then the operator should be replaced. For example, if user clicked on +, after that user clicked on – then subtract operation will be performed instead of addition
2)Sequence of operations should be implemented. For example, if user enters 5 and then + and then 4 and then –, it should compute 5+4 and display 9 in the textbox/label
If link does not work here is my code
import React from "react"
import "./style.css"
import "./App.css"
class Layout extends React.Component{
constructor(){
super()
this.state ={
text: "",
result: [],
prevResult: []
}
this.handleChange = this.handleChange.bind(this)
this.calculate = this.calculate.bind(this)
this.back = this.back.bind(this)
}
handleChange(event){
const {name, value, type, checked} = event.target
this.setState({[name]: value})
}
calculate(event){
this.setState((prevState) => ({
text: (eval(this.state.text) || "" ) + "",
result: [...prevState.result, this.state.text + " " ],
prevResult: [...prevState.prevResult, + (eval(this.state.text) || "" ) + " " ]
})
)
}
back(event){
const {name, value, type, checked} = event.target
type === "abc" ? this.setState({text: this.state.text.slice(0, -1)}) : this.setState({text: ""})
}
render(){
return(
<div >
<div className= "resultbar">
<input style= {{height: "30px", width: "200px", font: "20px" }}
name="text"
autoFocus="autofocus"
value={this.state.text}
onChange = {this.handleChange}
/>
</div>
<div className= "history">
<h2>History</h2>
<h3 style= {{color: "red" }}>{this.state.result} </h3>
<p>{this.state.prevResult}</p>
</div>
<div className="button">
<button
name= "text"
value = {this.state.text + "+"}
onClick= {this.handleChange}>+</button>
<button
name= "text"
value = {this.state.text + "-"}
onClick= {this.handleChange}>-</button>
<button
type= "adbc"
name= "text"
value = {this.state.text + "*"}
onClick= {this.handleChange}>*</button>
<button
name= "text"
value = {this.state.text + "/"}
onClick= {this.handleChange}>/</button>
<button
name= "text"
value = {this.state.text + "%"}
onClick= {this.handleChange}>%</button>
<button
name= "text"
value = {this.state.text + "("}
onClick= {this.handleChange}>(</button>
<button
name= "text"
value = {this.state.text + ")"}
onClick= {this.handleChange}>)</button>
<button
name= "text"
type= "dbac"
value= {this.state.text}
onClick = {this.calculate}>=</button>
<button
name= "text"
value = {this.state.text + "1"}
onClick= {this.handleChange}>1</button>
<button
name= "text"
value = {this.state.text + "2"}
onClick= {this.handleChange}>2</button>
<button
name= "text"
value = {this.state.text + "3"}
onClick= {this.handleChange}>3</button>
<button
name= "backspace"
onClick = {() => this.setState({
text: this.state.text.slice(0, -1)
})}> Ce</button>
<button
name= "text"
value = {this.state.text + "4"}
onClick= {this.handleChange}>4</button>
<button
name= "text"
value = {this.state.text + "5"}
onClick= {this.handleChange}>5</button>
<button
name= "text"
value = {this.state.text + "6"}
onClick= {this.handleChange}>6</button>
<button
name= "text"
type= "abc"
onClick = {this.back}
>C</button>
<button
name= "text"
value = {this.state.text + "7"}
onClick= {this.handleChange}>7</button>
<button
name= "text"
value = {this.state.text + "8"}
onClick= {this.handleChange}>8</button>
<button
name= "text"
value = {this.state.text + "9"}
onClick= {this.handleChange}>9</button>
<button
name= "backspace"
onClick = {() => this.setState({
text: this.state.text.slice(0, -1)
})}> ~</button>
<button
name= "text"
value = {this.state.text + "."}
onClick= {this.handleChange}>.</button>
<button
name= "text"
value = {this.state.text + "0"}
onClick= {this.handleChange}>0</button>
</div>
</div>
)
}
}
export default Layout
You need to check past string value, if last char is operator than update operator. Batter use calculator algorithm stack-based. Just push elements in stack if number, replace if operator, calculate if =.
- dont modify the value from the value of button (value={this.state.text + ")"})
- Write logic in function
// Clean up of code. https://codesandbox.io/s/eager-haze-gi30v
import React from "react";
import "./style.css";
import "./App.css";
const operators = ["+", "-", "/", "*", "%"];
class Layout extends React.Component {
constructor() {
super();
this.state = {
text: "",
result: [],
prevResult: []
};
this.handleChange = this.handleChange.bind(this);
this.calculate = this.calculate.bind(this);
this.onChange = this.onChange.bind(this);
}
handleChange(event) {
const { name, value } = event.target;
let text = this.state.text;
let lastChar = text.charAt(text.length - 1);
const isOperator = operators.indexOf(value) !== -1;
if (value === "=") {
this.setState(prevState => this.calculate(prevState));
} else if (value === "CE") {
this.setState({ text: text.slice(0, -1) });
} else if (value === "C") {
this.setState({ text: "" });
} else if (isOperator && operators.indexOf(lastChar) !== -1) {
text = text.substr(0, text.length - 1) + value;
this.setState({ [name]: text });
} else {
this.setState({ [name]: text + value });
}
}
onChange({ target }) {
this.setState({ text: target.value });
}
calculate(prevState) {
try {
const text = (eval(this.state.text) || "") + "";
return {
text,
result: [...prevState.result, this.state.text + " "],
prevResult: [...prevState.prevResult, +text]
};
} catch (event) {
return {
text: "error",
result: "error",
prevResult: "error"
};
}
}
render() {
const buttons = [
"+",
"-",
"*",
"/",
"%",
"(",
")",
"=",
"1",
"2",
"3",
"CE",
"4",
"5",
"6",
"C",
"7",
"8",
"9",
"~",
".",
"0"
];
return (
<div>
<div className="resultbar">
<input
style={{ height: "30px", width: "200px", font: "20px" }}
name="text"
autoFocus="autofocus"
value={this.state.text}
onChange={this.onChange}
/>
</div>
<div className="history">
<h2>History</h2>
<h3 style={{ color: "red" }}>{this.state.result} </h3>
<p>{this.state.prevResult}</p>
</div>
<div className="button">
{buttons.map(x => {
return (
<button name="text" value={x} onClick={this.handleChange}>
{x}
</button>
);
})}
</div>
</div>
);
}
}
export default Layout;