RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1173580
Accepted
corocoto
corocoto
Asked:2020-09-03 01:09:42 +0000 UTC2020-09-03 01:09:42 +0000 UTC 2020-09-03 01:09:42 +0000 UTC

为什么 currentVal 分配从键盘键入的最后一个字符?

  • 772

我决定将计算器的类组件重写为功能性组件。

面对这样一个事实,当您尝试从键盘输入数字时,只会记录和显示最后一个字符。

想知道我做错了什么。

下面附上组件代码:

import React, {useState, useEffect, useCallback} from 'react';
import styles from './Calculator.module.css';

import Display from '../../UI/Display/Display';
import Button from '../../UI/Button/Button';

const Calculator = (props) => {
    const [operation, setOperation] = useState(null);
    const [currentVal, setCurrentVal] = useState(0);
    const [prevVal, setPrevVal] = useState(0);
    const btnsVal = [
            'C', '√', 'x²', '/',
            '7', '8', '9', '*',
            '4', '5', '6', '-',
            '1', '2', '3', '+',
            '.', '0', 'Del', '='
    ];

    const btnsArr = btnsVal.map((val, index) =>
        <Button
            key={`${index}-${val}`}
            value={val}
            onClick={() => clickEventHandler(val)}
        />
    );

    const calcOperations = {
        '/': (prevValue, currentValue) => prevValue / currentValue,
        '*': (prevValue, currentValue) => prevValue * currentValue,
        '+': (prevValue, currentValue) => Number(prevValue) + Number(currentValue),
        '-': (prevValue, currentValue) => prevValue - currentValue,
        '=': currentValue => currentValue,
        '√': currentValue => Math.sqrt(currentValue),
        'x²': currentValue => currentValue**2
    };

    useEffect(() => {
        document.addEventListener('keydown', keydownEventHandler);
        return () => document.removeEventListener('keydown', keydownEventHandler);
    }, []);

    const keydownEventHandler = useCallback(({key}) => {
        if (btnsVal.includes(key) ){
            clickEventHandler(key);
        }else if (key === 'Backspace'){
            clickEventHandler('Del');
        }else if (key === ','){
            clickEventHandler('.');
        }else if (key === 'Enter'){
            clickEventHandler('=');
        }
    }, [btnsVal]);

    useEffect(() => {
        !currentVal && setCurrentVal('0');
        !prevVal && setPrevVal('0');
    }, [currentVal, prevVal]);

    const writeNum = (symbol) => {
        const value = (symbol === '.' || currentVal.toString() !== '0')
            ? currentVal  + symbol
            : symbol;
        if (Array.from(value).filter(item => item === '.').length < 2){
            setCurrentVal(value);
        }
    }

    const choiceOperation = (symbol) => {
        if (['√','x²'].includes(symbol)){
            const currVal = calcOperations[symbol](Number(currentVal) || prevVal);
            operation === '=' && setOperation(null);
            setCurrentVal(currVal);
            return;
        } else if (operation){
            setPrevVal(calcOperations[operation](prevVal, currentVal));
        }else {
            setPrevVal(currentVal);
        }
        setCurrentVal(0);
        setOperation(symbol);
    }

    const clickEventHandler = (symbol) => {
        if (/(\d|\.)/.test(symbol)) {
            writeNum(symbol);
        }else if (symbol === 'Del') {
            setCurrentVal(`${currentVal}`.slice(0, -1));
        }else if (symbol === 'C') {
            setOperation(null);
            setCurrentVal(0);
            setPrevVal(0);
        }else{
            choiceOperation(symbol);
        }
    }

    return (
        <div className={styles.Calculator}>
            <Display result={operation === '=' ? prevVal : currentVal}/>
            <div className={styles.btnsBlock}>{btnsArr}</div>
        </div>
    );
}

export default Calculator;
javascript
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Sergei Kirjanov
    2020-09-03T05:47:37Z2020-09-03T05:47:37Z

    (1) 最好使用以set*过去值作为输入的函数的形式。

    专门currentVal在渲染时使用,而不是在处理程序中。

    (2) 规定useEffect/的所有依赖项useCallback。从内部useEffect/ useCallback,您只能访问所描述的依赖项,或者在组件 ( set*) 的生命周期内不可变的依赖项。

    显然,例如,useEffectcaddEventListener必须依赖于keydownEventHandler.

    (3) 现在btnsVal在每次渲染和重置时重新创建keydownEventHandler。要使依赖项btnsVal起作用,它必须位于组件(或useMemo)旁边。

    • 2

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

  • 弹出队列。消息显示不正确

  • 是否可以在 for 循环中插入提示?

  • 如何将 JSON 请求中的信息输出到数据表 Vuetify vue.js?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5