3

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

1 Answer 1

4

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 =.

  1. dont modify the value from the value of button (value={this.state.text + ")"})
  2. 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;
Sign up to request clarification or add additional context in comments.

15 Comments

Updated on ur sample
@moeez-atlas I have cleanup code more check now. #moeez-atlas
yeah it looks much cleaner now. Thanks
can u please help with the second functionality. Having trouble with it.
Done Please check! sigh!! codesandbox.io/embed/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.