使用useState填充Input组件异常问题排查
问题:Input组件输入后仅保留最后一个字符,其余内容被清空
问题场景
在实现搜索提示功能时,尝试通过useState的setValue更新Input组件内容,但输入时每次只能保留最后一个字符,前面的内容会被清空。最初怀疑是React/Next.js Hooks使用错误,简化后的测试代码看似正常,但实际存在未暴露的依赖冲突。
最初简化测试代码
import { Input } from '@nextui-org/react'; import { useState } from 'react'; // ... const [value, setValue] = useState<string>('') // ... <Input value={value} onChange={event => setValue(event.currentTarget.value)} />
补充完整问题代码
后续排查发现问题源于未提及的react-hook-form的register属性:
import { useForm } from "react-hook-form"; import { Input } from '@nextui-org/react'; import { MdSearch } from 'react-icons/md'; // ... const { register, handleSubmit } = useForm() // ... <Input {...register("titleSearchTerms")} css={{width: '100%'}} size="lg" bordered onChange={event => setValue(event.currentTarget.value)} labelRight={<MdSearch></MdSearch>} />
问题原因
register与自定义onChange冲突:react-hook-form的register方法会自动为Input绑定onChange逻辑,用于同步表单状态,自定义的onChange会和它产生冲突,导致状态更新混乱,出现输入内容被清空的情况。- 错误使用
event.currentTarget:在Input的onChange事件中,应该使用event.target获取输入值,currentTarget指向绑定事件的元素本身,但这里用target更准确且符合常规用法。
解决方案
根据需求选择以下两种方式之一:
方案1:保留react-hook-form控制,通过watch监听值变化
如果需要该输入框参与表单管理,无需自定义onChange,改用watch监听表单字段的变化来更新搜索提示的状态:
import { useForm } from "react-hook-form"; import { useState, useEffect } from "react"; import { Input } from '@nextui-org/react'; import { MdSearch } from 'react-icons/md'; // ... const { register, handleSubmit, watch } = useForm() const [searchValue, setSearchValue] = useState<string>(''); // 监听表单字段变化,同步到搜索状态 useEffect(() => { const unsubscribe = watch((formValues) => { setSearchValue(formValues.titleSearchTerms || ''); }); return unsubscribe; }, [watch]); // ... <Input {...register("titleSearchTerms")} css={{width: '100%'}} size="lg" bordered labelRight={<MdSearch></MdSearch>} />
方案2:移除register,完全用useState控制
如果该输入框不需要参与react-hook-form的表单流程,直接移除register属性,用useState单独控制输入值:
import { useState } from "react"; import { Input } from '@nextui-org/react'; import { MdSearch } from 'react-icons/md'; // ... const [searchValue, setSearchValue] = useState<string>(''); // ... <Input value={searchValue} onChange={event => setSearchValue(event.target.value)} css={{width: '100%'}} size="lg" bordered labelRight={<MdSearch></MdSearch>} />
内容的提问来源于stack exchange,提问作者Marco Antonio Soares Júnior
相关产品推荐
相关产品推荐

