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

React问题:Input组件的defaultValue为何无法更新?

问题分析与解决方案

你的问题核心在于**defaultValue 只在组件首次挂载时生效,后续 props 变化不会触发它更新**——这是 React 非受控组件的特性,defaultValue 只是初始值,而非动态绑定的数据源。当 zipData 更新后,Input 组件并不会自动读取新的 defaultValue,所以才会出现数据不同步的情况。

结合你使用的表单库(从 useField、registerField 和 addressFormRef.current?.setErrors 来看,应该是类似 React Hook Form 这类表单管理库),正确的做法是让表单库统一管理字段值,而非依赖 defaultValue。下面是具体的修复步骤:

1. 获取 CEP 数据后,主动更新表单字段值

在 handleZipCode 函数中,成功获取 zip 数据时,除了更新 zipData,还要调用表单实例的 setValue 方法更新对应字段的值。这样表单库会维护字段状态,自动同步到绑定的 Input 组件:

const handleZipCode = useCallback( async ({ target }: ChangeEvent<HTMLInputElement>) => {
  const { value } = target;
  try {
    if (value.length === 9 && isDigit(value[8])) {
      const zip = await cep(value);
      if (zip?.city) {
        setZipData(zip);
        // 新增:调用表单的 setValue 方法更新地址字段
        addressFormRef.current?.setValue('user_address', zip.street);
        // 如有其他关联字段(如城市、州),可一并更新
        addressFormRef.current?.setValue('user_city', zip.city);
        addressFormRef.current?.setValue('user_state', zip.state);
      } else {
        addressFormRef.current?.setErrors({ user_zip_code: 'CEP not found' });
      }
    }
  } catch (e) {
    addressFormRef.current?.setErrors({ 
      user_zip_code: e.message ?? 'CEP not found' 
    });
  }
}, [isDigit] );

2. 移除 Input 组件的 defaultValue,交由表单库管理状态

表单库会自动维护字段值并同步到组件,因此不需要再手动传递 defaultValue:

<fieldset>
  <legend>Address</legend>
  <Input 
    mask='' 
    name='user_address' 
    placeholder='Rua um dois três' 
    {/* 移除 defaultValue,由表单库管理值的同步 */}
  />
</fieldset>

3. (可选)优化自定义 Input 组件的受控同步

如果你的 useField 钩子返回字段当前的 value,可以将 Input 改为受控模式,直接绑定 value 属性并监听变化:

const Input: React.FC<InputProps> = ({ name, ...rest }) => {
  const { fieldName, value, registerField, error } = useField(name);
  const inputRef = useRef(null);

  useEffect(() => {
    registerField({
      name: fieldName,
      ref: inputRef.current,
      path: 'value',
      setValue(ref: any, value: string) {
        ref.setInputValue(value);
      },
      clearValue(ref: any) {
        ref.setInputValue('');
      },
    });
  }, [fieldName, registerField]);

  // 监听表单字段值变化,同步到输入框
  useEffect(() => {
    if (inputRef.current && value !== undefined) {
      inputRef.current.setInputValue(value);
    }
  }, [value]);

  return (
    <Container>
      <ReactInputMask 
        ref={inputRef} 
        value={value} {/* 绑定受控值 */}
        {...rest} 
      />
      {error && <Error>{error}</Error>}
    </Container>
  );
};

这样当表单字段值更新时,Input 会自动同步最新内容,确保数据一致性。

总结来说,你之前的错误是依赖非受控组件的 defaultValue 实现动态更新,正确的思路是利用表单库的状态管理能力,主动更新字段值并让组件与表单状态绑定。

内容的提问来源于stack exchange,提问作者augusto amaral

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 14:12:34