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;
预期与实际
- 预期:输入框可自由输入字符,不会意外失焦
- 实际:输入单个字符后输入框失去焦点,无法继续输入
解决方案
核心原因
- 内部组件重复创建:
SortableItem和SortableList定义在Test组件内部,每次Test状态更新(比如输入字符触发setText)时,这两个组件会被重新定义,导致DOM元素销毁重建,输入框因此失焦。 - 状态共享冲突:所有输入框共用同一个
text状态,输入时触发全局状态更新,引发组件重渲染。 - 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
相关产品推荐
相关产品推荐

