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

React中自动填充地址输入致模态框重渲染关闭的解决方案咨询

解决CEP自动填充时模态框反复开闭的问题

问题根源

  1. 每次checkCep更新时调用reset会重置整个表单,清空用户已输入的其他字段,引发不必要的重渲染,甚至触发模态框状态异常。
  2. useCep Hook中的getCEP函数每次组件渲染都会重新创建,可能导致额外的重渲染。
  3. 未处理无效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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:25:21