TypeScript动态添加输入字段组仅返回输入首字符问题排查
解决React动态输入框仅能获取第一个字符的问题
你的问题核心是闭包陷阱:handleUser函数里直接引用了组件渲染时的info状态,当连续输入时,函数捕获的还是初始的旧状态,导致每次更新都只基于第一次输入前的状态,所以只能看到输入的第一个字符。你尝试的setInfo((prev) => ({ ...prev, [name]: value }))报错,是因为把数组当成对象来解构更新了,info是数组类型,不能这么处理。
修正后的代码
import { useState } from 'react'; const UserForm = () => { const [info, setInfo] = useState([{ name: "", email: "", age: 0, }]) const handleAddAnotherUser = () => { setInfo(prevInfo => [...prevInfo, { name: "", email: "", age: 0, }]) } const handleUser = (i: number, event: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = event.target; // 使用函数式更新获取最新状态,避免闭包陷阱 setInfo(prevInfo => { // 拷贝原数组,避免直接修改原状态 const newInfo = [...prevInfo]; // 拷贝要修改的用户对象,保证状态不可变性 newInfo[i] = { ...newInfo[i], [name]: name === 'age' ? Number(value) : value }; return newInfo; }); } return ( <> {info.map((item, i) => ( // 给列表元素添加唯一key,React列表渲染必须项 <div key={i}> <input id={`name-${i}`} // 每个输入框id要唯一,避免冲突 name="name" type="text" placeholder="Joe Bloggs" value={item.name} onChange={(event) => handleUser(i, event)} /> <input id={`email-${i}`} name="email" type="email" placeholder="hello@email.com" value={item.email} onChange={(event) => handleUser(i, event)} /> <input id={`age-${i}`} name="age" type="number" placeholder="34" value={item.age} onChange={(event) => handleUser(i, event)} /> </div> ))} <button onClick={handleAddAnotherUser}>Add Another</button> </> ) } export default UserForm;
关键修正点
- 函数式状态更新:用
setInfo(prevInfo => ...)代替直接引用info,确保每次更新都能拿到最新的状态,解决闭包导致的旧状态问题。 - 保证状态不可变性:修改用户对象时创建新对象
{ ...newInfo[i], [name]: ... },而非直接修改原对象,符合React状态更新的最佳实践。 - 唯一标识处理:给每个输入框设置唯一
id(如name-${i})避免冲突;列表元素添加key,帮助React高效渲染列表。 - 类型适配:针对
age字段将输入值转为数字类型,避免字符串存入状态导致的类型不一致问题。
内容的提问来源于stack exchange,提问作者KG 01001011 01000111
相关产品推荐
相关产品推荐

