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

React应用输入框输入单个字符后失焦问题求助

问题:React输入框输入单个字符后失去焦点

在React应用中使用输入框时遇到问题:输入框仅能输入一个字符,之后就会失去焦点,无法继续输入更长文本。

相关代码

import React, { useState } from 'react';
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';


function Test() {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);
  const [text, setText] = useState('');

  // Define a functional component for your sortable item
  const SortableItem = SortableElement(({ value }) => {
    return <li>{value}<input value={text} onChange={(e) => setText(e.target.value)}/></li>;
  });

  // Create a sortable list component
  const SortableList = SortableContainer(({ items }) => {
    return (
      <ul>
        {items.map((value, index) => (
          <SortableItem key={`item-${index}`} index={index} value={value} />
        ))}
      </ul>
    );
  });

  const addItem = () => {
    const newItem = `Item ${items.length + 1}`;
    setItems([...items, newItem]);
  };

  const onSortEnd = ({ oldIndex, newIndex }) => {
    setItems(prevItem => (arrayMoveImmutable(prevItem, oldIndex, newIndex)));
  };

  return (
    <div>
      <button onClick={addItem}>Hozzáadás</button>
      <SortableList items={items} onSortEnd={onSortEnd} />
    </div>
  );
}

export default Test;

预期与实际

  • 预期:输入框可自由输入字符,不会意外失焦
  • 实际:输入单个字符后输入框失去焦点,无法继续输入

解决方案

核心原因

  1. 内部组件重复创建:SortableItem和SortableList定义在Test组件内部,每次Test状态更新(比如输入字符触发setText)时,这两个组件会被重新定义,导致DOM元素销毁重建,输入框因此失焦。
  2. 状态共享冲突:所有输入框共用同一个text状态,输入时触发全局状态更新,引发组件重渲染。
  3. key值不稳定:使用列表索引作为SortableItem的key,排序或新增项时key会对应到不同元素,触发不必要的组件重新挂载。

修复代码

import React, { useState } from 'react';
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';

// 将可排序组件移到外部,避免重复创建
const SortableItem = SortableElement(({ value, inputValue, onInputChange }) => {
  return (
    <li>
      {value}
      <input value={inputValue} onChange={(e) => onInputChange(e.target.value)} />
    </li>
  );
});

const SortableList = SortableContainer(({ items, inputValues, onInputChange }) => {
  return (
    <ul>
      {items.map((value, index) => (
        <SortableItem 
          key={`item-${value}-${index}`} // 用内容+索引生成更稳定的key
          index={index} 
          value={value} 
          inputValue={inputValues[index] || ''}
          onInputChange={(val) => onInputChange(index, val)}
        />
      ))}
    </ul>
  );
});

function Test() {
  const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);
  // 用数组维护每个输入框的独立状态
  const [inputValues, setInputValues] = useState([]);

  const addItem = () => {
    const newItem = `Item ${items.length + 1}`;
    setItems([...items, newItem]);
    setInputValues([...inputValues, '']); // 新增项时初始化对应输入状态
  };

  const onSortEnd = ({ oldIndex, newIndex }) => {
    setItems(prevItems => arrayMoveImmutable(prevItems, oldIndex, newIndex));
    setInputValues(prevValues => arrayMoveImmutable(prevValues, oldIndex, newIndex)); // 同步输入状态顺序
  };

  const handleInputChange = (index, value) => {
    const newInputValues = [...inputValues];
    newInputValues[index] = value;
    setInputValues(newInputValues);
  };

  return (
    <div>
      <button onClick={addItem}>Hozzáadás</button>
      <SortableList 
        items={items} 
        onSortEnd={onSortEnd} 
        inputValues={inputValues}
        onInputChange={handleInputChange}
      />
    </div>
  );
}

export default Test;

修复说明

  • 将SortableItem和SortableList移到Test组件外部,避免每次状态更新都重新创建组件。
  • 用数组inputValues维护每个输入框的独立状态,避免全局状态更新引发的重渲染冲突。
  • 使用value+index作为key,保证key的稳定性,减少不必要的组件挂载。
  • 排序时同步输入状态的顺序,确保排序后输入框内容对应正确的列表项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:45:54