React BMI追踪器设置state后组件未重新渲染问题咨询
问题根因及修复方案
根因分析
- 你将
dates、bmiResults、dataLog三个数组定义为组件外部的全局变量,没有使用React状态管理,React无法感知普通变量的变更,不会触发组件重渲染 - 更新
bmiAxis和dateAxis状态时,直接修改原数组后传入原数组引用,React浅比较判断引用未发生变化,不会触发重渲染 Logs组件接收的是普通全局变量dataLog而非状态,变量变更无法驱动组件更新- 计算BMI的逻辑存在单位错误:用户输入的身高单位是厘米,你直接用厘米值计算,没有转换为米,会导致BMI结果完全错误
- 原有日期计算逻辑中未对月份做+1处理,JS的
Date.getMonth()返回值为0-11,会导致月份显示错误
修复代码(仅修改InputContainer组件即可)
import React, { useState, useRef, useEffect } from 'react'; import Graph from '../Graph/Graph'; import Logs from '../Logs/logs'; import './InputContainer.scss'; export default function InputContainer() { const [result, setBmiResult] = useState(''); const [height, setHeight] = useState(''); const [weight, setWeight] = useState(''); // 状态初始值改为数组 const [bmiAxis,setBmiAxis] = useState([]); const [dateAxis,setDateAxis] = useState([]); // dataLog改为状态管理 const [dataLog, setDataLog] = useState([]); const calculateButton = useRef(null); const firstUpdate = useRef(true); useEffect(() => { calculateButton.current.disabled = isNaN(parseFloat(height) && parseFloat(weight)) ? true : false; }, [height, weight]); useEffect(() => { if (firstUpdate.current) { firstUpdate.current = false; return } const date = new Date(); // 月份+1修正显示 const currentDate = `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()}`; const dataLogElement = <div className="test"> <div className="bmi-and-date"> <p className="bmi"> BMI: {result} </p> <p className="date"> Date: {currentDate} </p> </div> <div className="height-and-weight"> <p className="height"> Height: {height}cm </p> <p className="weight"> Weight: {weight}kg </p> </div> </div>; // 用展开运算符生成新数组,触发重渲染 setDataLog(prev => [...prev, dataLogElement]); setDateAxis(prev => [...prev, currentDate]); setBmiAxis(prev => [...prev, result]); }, [result, height, weight]) const calculate = () => { // 厘米转米修正BMI计算逻辑 const bmi = (parseFloat(weight) / (parseFloat(height)/100) ** 2).toFixed(2) setBmiResult(parseFloat(bmi)) // 计算完成清空输入框优化体验 setHeight('') setWeight('') } return ( <> <div className='input-container'> <h1>BMI Tracker</h1> <div className="input"> <div className="height"> <h3>Enter Your Height in CM</h3> <input type="number" onChange={(e) => setHeight(e.target.value)} value={height} /> </div> <div className="weight"> <h3>Enter Your Weight in Kg</h3> <input type="number" onChange={(e) => setWeight(e.target.value)} value={weight} /> </div> </div> <button className='calculate' onClick={calculate} ref={calculateButton}>Calculate</button> </div> <Graph bmi={result} dates={dateAxis} results={bmiAxis} /> <Logs element={dataLog}/> </> ) }
内容的提问来源于stack exchange,提问作者Marwane Elalama
相关产品推荐
相关产品推荐

