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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:45:04