React.js中使用for循环获取输入框值求和异常的原因是什么?
问题原因分析
- React状态更新为异步批处理模式,
setGrade调用后不会立刻修改totalGrade的值,当前addGrade函数内捕获的totalGrade始终是本次渲染周期的初始值。你在循环中多次调用setGrade时,所有计算都基于同一个旧的totalGrade,只有最后一次setGrade会生效,最终结果就是「最后一个输入框的值 + 初始旧总和」,自然出现只累加最后一个输入值、无法重置的问题。 - 你调用的
setGrade(0)只是提交了一个状态更新请求,不会立刻把当前作用域里的totalGrade改成0,后续循环的计算还是用的重置前的旧值,所以重置逻辑完全没有生效。 - 额外问题点:直接在
rows中存储React元素不是最佳实践,后续如果要修改输入框的配置会非常麻烦,更推荐存储输入框的元数据,渲染时再遍历生成Inputs组件。
修复后的代码示例
function Start(){ // 仅存储输入框id元数据,不存组件实例 const [inputIds, setInputIds] = useState([1]); const [totalGrade, setGrade] = useState(0); const addInput = () =>{ setInputIds(prev => [...prev, prev.length + 1]); } const addGrade = () =>{ // 先在局部变量计算完总和,再一次性更新状态 let sum = 0; for(let id of inputIds){ const val = document.getElementById(id.toString())?.value; sum += parseInt(val || 0, 10); } setGrade(sum); } return( <div> <h1>计算GPA</h1> {inputIds.map(id => <Inputs key={id} label={id.toString()} />)} <button className="button2" onClick={addInput}>新增输入框</button> <button className="button2" onClick={addGrade}>计算总分</button> <h2>总分:{totalGrade}</h2> </div> ); }
补充说明
- 修复后的代码把输入框的id存在数组里,渲染时遍历生成组件,避免直接存储React元素带来的不可控问题
- 求和逻辑先在局部变量里算完最终总和,再一次性更新
totalGrade,避开了异步状态更新的坑 - 代码里补充了空值判断,避免输入框为空时
parseInt返回NaN导致计算错误 - 注意React里给元素加类名要用
className而非原生的class,否则属性不会生效
内容的提问来源于stack exchange,提问作者Alfonso Lima
相关产品推荐
相关产品推荐

