You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React:如何更新依赖状态的变量——D&D属性修正值计算问题

D&D角色表属性修正值组件问题解决

问题描述

我正在使用React开发《龙与地下城》(Dungeons and Dragons)角色表,目前卡在属性修正值组件上:通过React.useState(),点击箭头按钮可修改红色圈中的count值(当前初始为8)。我希望将固定为“15”的修正值改为动态计算值,公式是Math.floor((count-10)/2),尝试用onChange实现但失败了,代码如下:

import React from "react"
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
import Button from '@mui/material/Button';

export default function StatBox(props) {
  const[count, setCount] = React.useState(8)

  const incrementCount = () => {
    setCount(count+1);

}

let modifier = "15"
if (count && !isNaN){
  const modifierNum = Math.floor(Number(count)-10/2)
  if(modifierNum > 0){
    modifier = "+" + modifierNum
  }
  else{
    modifier = modifierNum.toString()
  }
}


const decrementCount = () => {
  setCount(count-1);  
}

    return (
      <div className="col text-center border border-danger rounded mt-2 mb-2">
        <label>{props.stats}</label>
        <div className="d-and-d-statbox-modifier">{modifier}</div>
        <div className="row justify-content-center mb-2">
          <Button
            onClick={decrementCount}
            onChange={(e) => count.onChange(count, e.target.value)}
            size="sm"
            variant="contained"
            color="error"
          >
            <ArrowBackIosIcon fontSize="small" />
          </Button>
          <div>
            <span className="mx-1 border-danger text-center dndstatrow">
              {count}
            </span>
          </div>
          <Button
            onClick={incrementCount}
            onChange={(e) => count.onChange(count, e.target.value)}
            size="sm"
            variant="contained"
            color="error"
          >
            <ArrowForwardIosIcon fontSize="small" />
          </Button>
        </div>
      </div>
    );
}

错误分析

  • onChange事件误用:Button组件不需要绑定onChange事件,你写的count.onChange(count, e.target.value)完全无效——count是React状态值,不是DOM元素,没有onChange方法,直接删除这两行即可。
  • 公式优先级错误:你的计算式Math.floor(Number(count)-10/2)中,除法优先级高于减法,实际计算的是count - 5,不符合需求。正确写法是给count-10加括号:Math.floor((Number(count)-10)/2)。
  • 条件判断无效:if (count && !isNaN)中的!isNaN是判断isNaN函数本身是否为真(永远是true),应该改成!isNaN(count)来验证count是否为有效数字。
  • 初始值冗余:modifier初始设为"15"完全没必要,因为count初始值是8(有效数字),直接基于count计算即可。

修正后的代码

import React from "react"
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
import Button from '@mui/material/Button';

export default function StatBox(props) {
  const [count, setCount] = React.useState(8)

  const incrementCount = () => {
    setCount(count + 1);
  }

  const decrementCount = () => {
    setCount(count - 1);  
  }

  // 动态计算属性修正值
  const modifierNum = Math.floor((count - 10) / 2);
  const modifier = modifierNum > 0 ? `+${modifierNum}` : modifierNum.toString();

  return (
    <div className="col text-center border border-danger rounded mt-2 mb-2">
      <label>{props.stats}</label>
      <div className="d-and-d-statbox-modifier">{modifier}</div>
      <div className="row justify-content-center mb-2">
        <Button
          onClick={decrementCount}
          size="sm"
          variant="contained"
          color="error"
        >
          <ArrowBackIosIcon fontSize="small" />
        </Button>
        <div>
          <span className="mx-1 border-danger text-center dndstatrow">
            {count}
          </span>
        </div>
        <Button
          onClick={incrementCount}
          size="sm"
          variant="contained"
          color="error"
        >
          <ArrowForwardIosIcon fontSize="small" />
        </Button>
      </div>
    </div>
  );
}

修改说明

  1. 移除了按钮上无效的onChange事件绑定
  2. 修正了属性修正值的计算公式,确保运算顺序正确
  3. 简化了修正值的生成逻辑,直接通过三元表达式处理正负号显示
  4. 调整了代码结构,将计算逻辑放在事件处理函数之后,可读性更强

内容的提问来源于stack exchange,提问作者Walid Daniel Dib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:55:16