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

React输入框无法持续输入:点击后自动禁用问题求助

React输入框自动"失去焦点"问题解决方案

问题现象

开发React应用时遇到异常:每次点击输入框输入内容后,输入框会立刻失去焦点(表现类似被禁用);再次点击可重新输入,但输入后又会重复上述问题。

用户提供代码

TimeInputRow组件

const TimeInputRow = ({ data, onFieldChange, onAddRow }) => {
    console.log(data)
    const {existing_date,  time_start, time_end, percent_to_count, days_addtion } = data;
    
    console.log(existing_date)
    // const formattedDate = new Date(existing_date).toLocaleDateString('en-GB');

    return (
      <div className='d-f time-adding'>
        {/* Use formattedDate instead of date */}
        <input type="text" value={existing_date || ""} onChange={(e) => onFieldChange('existing_date', e.target.value)} />

        <input type="text" pattern="[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" value={time_start} onChange={(e) => onFieldChange('time_start', e.target.value)} />
        <input type="text" pattern="[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" value={time_end} onChange={(e) => onFieldChange('time_end', e.target.value)} />
        <input type="number" placeholder="Percent Count" value={percent_to_count} onChange={(e) => onFieldChange('percent_to_count', parseInt(e.target.value))} />
        <input type="text" placeholder="Days Addtion" value={days_addtion} onChange={(e) => onFieldChange('days_addtion', e.target.value)} />
        <button onClick={onAddRow} className='add-row'><FaRegPlusSquare /></button>

      </div>
    );
};

字段变更处理代码

const handleFieldChange = (index, field, value) => {
    const newRows = [...rows];
    newRows[index][field] = value;
    setRows(newRows);
};

{rows.map((data, index) => (
    <div key={index} className='d-f'>
        <TimeInputRow
            key={index}
            data={data}
            onFieldChange={(field, value) => handleFieldChange(index, field, value)}
            onAddRow={handleAddRow}
        />
        <button className='remove-row' onClick={() => handleRemoveRow(index)}><FaRegTrashAlt /></button>
    </div>
))}
<button className='btn btn-primary' onClick={handleSubmit}>Save</button>

问题根源

  1. 用index作为React元素的key:数组更新时index会变动,React的diff算法会错误地复用/重建组件,导致输入框失去焦点,看起来像被禁用。
  2. 状态更新的不可变性不足:虽然复制了数组,但直接修改内部对象的属性,React可能无法正确识别状态变化,引发不必要的重渲染。
  3. 部分输入框value无兜底处理:比如time_start如果初始值为undefined,会导致受控组件状态异常。

修复方案

1. 给每行数据加唯一ID,替换index作为key

初始化rows时给每个对象添加唯一标识:

// 初始化示例
const [rows, setRows] = useState([
    {
        id: Date.now(),
        existing_date: "",
        time_start: "",
        time_end: "",
        percent_to_count: "",
        days_addtion: ""
    }
]);

渲染时用这个唯一ID作为key:

{rows.map((data, index) => (
    <div key={data.id} className='d-f'>
        <TimeInputRow
            key={data.id}
            data={data}
            onFieldChange={(field, value) => handleFieldChange(index, field, value)}
            onAddRow={handleAddRow}
        />
        <button className='remove-row' onClick={() => handleRemoveRow(index)}><FaRegTrashAlt /></button>
    </div>
))}

2. 优化状态更新逻辑,严格遵循不可变性

修改handleFieldChange,用函数式更新+对象扩展运算符返回全新对象:

const handleFieldChange = (index, field, value) => {
    setRows(prevRows => prevRows.map((row, i) => 
        i === index ? { ...row, [field]: value } : row
    ));
};

3. 给所有输入框的value添加兜底处理

避免value为undefined导致受控组件异常:

<input type="text" pattern="[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" value={time_start || ""} onChange={(e) => onFieldChange('time_start', e.target.value)} />
<input type="text" pattern="[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" value={time_end || ""} onChange={(e) => onFieldChange('time_end', e.target.value)} />
<input type="number" placeholder="Percent Count" value={percent_to_count || ""} onChange={(e) => onFieldChange('percent_to_count', parseInt(e.target.value) || 0)} />
<input type="text" placeholder="Days Addtion" value={days_addtion || ""} onChange={(e) => onFieldChange('days_addtion', e.target.value)} />

修复逻辑说明

  • 唯一ID作为key能让React准确识别每个组件,避免数组变动时错误销毁/重建组件,保证输入框焦点稳定。
  • 不可变状态更新能让React正确检测状态变化,只更新需要变动的组件,提升性能同时避免异常渲染。
  • 兜底处理value确保受控组件状态始终有效,不会因undefined导致输入框行为异常。

内容的提问来源于stack exchange,提问作者Siva MCA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:30:15