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

React Hooks更新对象数组时遇值回退问题求助

问题排查与修复方案

核心问题1:输入框未使用受控绑定

你用了defaultValue初始化输入框值,但这是非受控组件的用法——它只会在组件第一次渲染时生效,后续状态更新不会同步到输入框。哪怕你更新了gameNumberFields状态,输入框也不会显示新值,看起来就像“值变回旧值”。

修复: 把defaultValue={field.value}改成value={field.value},让输入框成为受控组件,和状态实时绑定。


核心问题2:状态更新逻辑错误

你的事件处理函数里,每次更新都创建新数组并只推入修改后的对象——这会直接替换原数组,若原数组有多个元素,其他元素会全部丢失。而且直接依赖当前的gameNumberFields状态,可能因为闭包问题拿到旧状态,导致更新失效。

修复: 使用React函数式更新获取最新状态,复制原数组并修改对应元素:

const handleGameNumberChange = (event, index) => {
    const gameNum = event.target.value;
    setGameNumberFields(prevFields => {
        const newFields = [...prevFields];
        newFields[index] = { ...newFields[index], value: gameNum };
        return newFields;
    });
};

核心问题3:Refs管理混乱

你在render的map循环里直接往elemRefs数组push新的createRef,每次组件渲染都会执行这段代码,导致refs数组不断累积重复的ref,后续autoTab功能可能出错。

修复: 用useRef存储refs数组,每次map时更新对应索引的ref:

// 初始化refs
const elemRefs = useRef([]);

// 渲染输入框时更新refs
return gameNumberFields.map((field, index) => {
    elemRefs.current[index] = React.createRef();
    return (
        <div className='d-inline-block ticket-number-inputs' key={`game-numbers--${index}`}>
            <input
                // ...其他属性
                data-index={index}
                ref={elemRefs.current[index]}
                onBlur={(event) => handleGameNumberChange(event, index)}
                onKeyUp={(event) => autoTab(event, elemRefs.current)}
            />
            <span className='dash'>&mdash;</span>
        </div>
    );
});

完整修复后的关键代码片段

初始化状态与refs

const [gameNumberFields, setGameNumberFields] = useState(scratchTicketFields?.gameNumberFields ?? []);
const elemRefs = useRef([]);

输入框渲染

return gameNumberFields.map((field, index) => {
    elemRefs.current[index] = React.createRef();
    return (
        <div className='d-inline-block ticket-number-inputs' key={`game-numbers--${index}`}>
            <input
                type='text'
                id={field.name}
                data-index={index}
                ref={elemRefs.current[index]}
                className='theme-input'
                placeholder={field.placeholder}
                size={field.size}
                maxLength={field.size}
                value={field.value}
                onBlur={(event) => handleGameNumberChange(event, index)}
                onKeyUp={(event) => autoTab(event, elemRefs.current)}
                required
            />
            <span className='dash'>&mdash;</span>
        </div>
    );
});

事件处理函数

const handleGameNumberChange = (event, index) => {
    const gameNum = event.target.value;
    setGameNumberFields(prevFields => {
        const newFields = [...prevFields];
        newFields[index] = { ...newFields[index], value: gameNum };
        return newFields;
    });
};

内容的提问来源于stack exchange,提问作者Ryan DesRoches

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 02:18:20