React中自动填充地址输入致模态框重渲染关闭的解决方案咨询
解决CEP自动填充时模态框反复开闭的问题
问题根源
- 每次
checkCep更新时调用reset会重置整个表单,清空用户已输入的其他字段,引发不必要的重渲染,甚至触发模态框状态异常。 useCepHook中的getCEP函数每次组件渲染都会重新创建,可能导致额外的重渲染。- 未处理无效CEP的情况(比如ViaCEP API返回的错误数据),会导致错误内容更新到表单。
解决方案
1. 优化useCep Hook,稳定函数引用并处理无效CEP
import { useState, useCallback } from 'react' import { api } from 'services/apiClient' interface Cep { bairro: string logradouro: string localidade: string uf: string erro?: boolean // 适配API返回的错误标识 } export function useCep() { const [checkCep, setCheckCep] = useState<Cep>() // 用useCallback稳定函数引用,避免组件重复创建函数 const getCEP = useCallback(async (e) => { const cep = e.target.value.replace(/\D/g, '') // 仅当CEP长度为8时发起请求,避免无效调用 if (cep.length !== 8) { setCheckCep(undefined) return } try { const { data } = await api.get(`https://viacep.com.br/ws/${cep}/json/`) // 处理API返回的无效CEP情况 if (data.erro) { setCheckCep(undefined) return } setCheckCep(data) } catch (err) { console.log(err) setCheckCep(undefined) } }, []) return { checkCep, getCEP } }
2. 替换reset为setValue,局部更新表单字段
不要重置整个表单,而是单独更新需要填充的地址字段,避免丢失用户已输入内容,减少重渲染:
import { useFormContext, useWatch } from 'react-hook-form' const { control, register, setValue, formState: { errors } } = useFormContext() const { checkCep, getCEP } = useCep() // 监听当前索引对应的CEP字段,避免全局监听 const currentCep = useWatch({ control, name: `responsible.${index}.cep` }) useEffect(() => { if (!checkCep) return // 单独更新每个地址字段,不影响其他已输入内容 setValue(`responsible.${index}.address`, checkCep.logradouro) setValue(`responsible.${index}.district`, checkCep.bairro) setValue(`responsible.${index}.city`, checkCep.localidade) setValue(`responsible.${index}.state`, checkCep.uf) }, [checkCep, setValue, index]) // 输入框改为text类型,避免number类型的输入限制 <Input name="cep" type="text" label="Cep" {...register(`responsible.${index}.cep`)} error={errors?.responsible?.[index]?.cep} onBlur={(e) => getCEP(e)} />
3. 确保模态框状态独立
检查模态框的显示逻辑,确保其open状态由独立的状态变量控制(比如const [modalOpen, setModalOpen] = useState(false)),不依赖表单字段或formState的变化,避免表单更新时触发模态框开闭。
关键说明
useCallback包裹getCEP可稳定函数引用,减少不必要的组件重渲染。setValue局部更新字段替代reset,既保留用户输入,又避免大面积重渲染触发模态框异常。- 增加无效CEP的处理逻辑,避免错误数据进入表单。
内容的提问来源于stack exchange,提问作者Coraggio
相关产品推荐
相关产品推荐

