React Calculator:多点问题和方程问题

如何解决React Calculator:多点问题和方程问题

我已经在React中创建了可运行的计算器,但有两点需要弄清楚:

  • 我想确保如果用户已经单击过一次,则不能输入第二个点
  • 我希望方程式使用最后一个运算符(例如5 *-+ 5应该产生10的输出)

我仍然是一个初学者,所以我需要一个简单的代码来完成这些工作,而且我似乎无法弄清楚。非常感谢!这是到目前为止我的完整代码和Codepen链接:https://codepen.io/JuliaAyres/pen/dyXGvbO

class App extends React.Component {

   constructor(props){
    super(props);
    this.state = {
      display:'0'
    }
    this.changeValue = this.changeValue.bind(this);
    this.equalEval = this.equalEval.bind(this);
  }

  changeValue(event){
    if(event.target.value==='CE'){
      this.setState({display: '0'});
    }else{
      this.setState({
        display: (this.state.display==="0" ? event.target.value : this.state.display + event.target.value)
      });
    }
  }

  equalEval(){
    this.setState({
        display: eval(this.state.display)
    });
  }

  render() {
    return (
      <div className="App">

        <div className="calculator">
            <div id="display">{this.state.display}</div>
          
            <div className="buttongrid">

            <button value="CE" id="clear"  className="button" onClick={this.changeValue}>CE</button>
            <button value=" / " id="divide"  className="button" onClick={this.changeValue}>/</button>
            <button value=" * " id="multiply"  className="button" onClick={this.changeValue}>x</button>
            
            <button value="7" id="seven" className="button" onClick={this.changeValue}>7</button>
            <button value="8" id="eight" className="button" onClick={this.changeValue}>8</button>
            <button value="9" id="nine" className="button" onClick={this.changeValue}>9</button>
            <button value=" - " id="subtract" className="button" onClick={this.changeValue}>-</button>
            
            <button value="4" id="four" className="button" onClick={this.changeValue}>4</button>
            <button value="5" id="five" className="button" onClick={this.changeValue}>5</button>
            <button value="6" id="six" className="button" onClick={this.changeValue}>6</button>
            <button value=" + " id="add" className="button" onClick={this.changeValue}>+</button>

            <button value="1" id="one" className="button" onClick={this.changeValue}>1</button>
            <button value="2" id="two" className="button" onClick={this.changeValue}>2</button>
            <button value="3" id="three" className="button" onClick={this.changeValue}>3</button>
            

            <button value="." id="decimal" className="button" onClick={this.changeValue}>.</button>
            <button value="0" id="zero" className="button" onClick={this.changeValue}>0</button>
            <button value=" = " id="equals" className="button" onClick={this.equalEval}>=</button>
            

            </div>
      </div>
      </div>
    );
  }
}

ReactDOM.render(<App />,document.getElementById('root'));

解决方法

对于十进制情况,我建议添加一个布尔状态(我们将其称为allowDecimal)以启用或禁用最初设置为true的十进制按钮。

然后在render()内,将小数按钮的禁用属性设置为allowDecimal的反面。原因是您想在allowDecimal为假时禁用按钮:

<button value="." id="decimal" className="button" onClick={this.changeValue} disabled={!this.state.allowDecimal}>.</button>

然后在changeValue()内,添加另一个if语句以检查event.target.value === '.'。如果是,请将allowDecimal状态设置为false,这将禁用该按钮。您可以在用户按下等于或CE时再次将allowDecimal设置回true。希望这是有道理的。

,

解决起来很有趣,但是有一些问题(不幸的是,对初学者不太友好):

下面的代码利用以下Javascript方法/表达式:

1。)建议避免使用eval,因为它可能unsafe且易碎。您可以使用math-expression-evaluator之类的库来处理字符串数学表达式。但是,即使那样,该库似乎也无法处理无效的表达式(例如1 + 1 +),因此您必须trycatch任何错误。

let result;
try {
  result = mexp.eval(this.state.display);
} catch (error) {
  alert(error.message);
  result = "NaN";
}

2。)当涉及小数时,您需要将字符串划分为字符串数组:"1.1 + 1.2" => ["1.1"," + ","1.2"]为什么?因为您要确定数组中的最后一个值是否已经包含小数,以及如果再次按下小数按钮,是否要更新display状态。

目前的情况是,必须手动检查每个按下的按钮值,并确定是否单击了allowDecimal值高的按钮,并且您是否要切换此 +,-,*,/状态如果已经存在小数,则必须确定是否更新此display状态(这需要遍历整个display字符串并找到最后一个 +,/实例,然后确定是否最后一个值已经有一个小数了-您可以想象,这效率很低。)

相反,如果数组中的最后一个值已包含小数并且按下了小数按钮,则可以确定是否更新display值:

 /*
   split string in array of strings by space(" ")
   
   for example: "1.1 + 1.2" becomes ["1.1","1.2]
 */
 const arrValue = prevState.display.split(" ");

 /*
  "lastValueHasDecimal" checks that the last value in the array doesn't contain 
   "." and that the current value of the button pressed is a decimal. 

   In short,if the last value already contains a decimal and the decimal button 
   was pressed,return the previous "display" state; otherwise,update the state.
  
   str.indexOf("x") works by finding the index of "x" within a string
   a value greater than -1 means "x" was found at an index within the string
  
   for example: "1.2" has three indexes: [0,1,2] -- arrays start at index 0
   and a decimal (".") can be found at index 1:
   [
     0: "1",1: ".",2: "2"
   ]
 */
const lastValueHasDecimal =
  arrValue[arrValue.length - 1].indexOf(".") > -1 && value === ".";

3。)使用form代替divbutton。这使其对开发人员更加友好。使用表单时,按钮必须包含带有typebutton的{​​{1}}属性!

演示

Edit Simple React Calculator

代码

App.js

submit

fields.js

import React from "react";
import mexp from "math-expression-evaluator";
import calculatorFields from "./fields";
import "./styles.css";

const initialState = {
  display: "",result: ""
};

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = initialState;
    this.changeValue = this.changeValue.bind(this);
    this.resetDisplay = this.resetDisplay.bind(this);
    this.equalEval = this.equalEval.bind(this);
  }

  changeValue({ target: { value } }) {
    /* 
      setState accepts a function that accepts the current state as an argument
      and expects a state object to be returned:
      (prevState) => { return { ... } };
 
      since you're checking whether or not the last value within "display" 
      has a decimal before updating the state,you'll want to conditionally update
      the state with `value` based upon the "lastValueHasDecimal" expression.

      if(lastValueHasDecimal) is true return prevState.display
      else if false return prevState.display.concat(value)

      prevState.display.concat(value)
      is the same as:
      prevState.display + value
    */
    this.setState((prevState) => {
      const arrValue = prevState.display.split(" ");
      const lastValueHasDecimal =
        arrValue[arrValue.length - 1].indexOf(".") > -1 && value === ".";

      return {
        display: lastValueHasDecimal
          ? prevState.display
          : prevState.display.concat(value),result: ""
      };
    });
  }

  // if "CE" is pressed,return to "initialState" defined above
  resetDisplay() {
    this.setState(initialState);
  }

  // when the form is submitted...
  equalEval(e) {
    // prevent the page from refreshing,the "default" action of submitting a form
    e.preventDefault();

    // evaluate the "display" expression
    let result;
    try {
      result = mexp.eval(this.state.display);
    } catch (error) {
      alert(error.message);
      result = "NaN";
    }

    // update "result" with the result of evaluation
    this.setState({ result });
  }

  render() {
    const { display,result } = this.state;

    return (
      <div className="app">
        <form onSubmit={this.equalEval} className="calculator">
          <div id="display">
            <input
              className="result"
              disabled
              type="text"
              value={!result ? display : result}
            />
          </div>
          <div className="buttongrid">
            <button
              type="button"
              id="clear"
              className="button"
              onClick={this.resetDisplay}
            >
              CE
            </button>
            {calculatorFields.map(({ id,value }) => (
              <button
                key={id}
                type="button"
                value={value}
                id={id}
                className="button"
                onClick={this.changeValue}
              >
                {value}
              </button>
            ))}
            <button
              type="submit"
              id="equals"
              className="button"
              disabled={!display}
            >
              =
            </button>
          </div>
        </form>
      </div>
    );
  }
}

如果没有任何意义,请随时提问。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res