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

使用forwardRef时React自定义输入框失焦问题求助

问题原因及解决方案

核心原因

  1. 自定义组件引用不稳定:如果你的EuiCellPhoneNumberFieldText是在表单组件内部定义的,或者通过内联方式传递给inputComponent(比如inputComponent={() => <EuiCellPhoneNumberFieldText />}),每次表单重渲染时都会创建全新的组件实例。React会卸载旧组件、挂载新组件,直接导致输入框失焦。
  2. Ref传递不完整:即便用了forwardRef,如果没把接收到的ref正确传递给自定义组件内部的底层<input>元素,PhoneInputWithCountry就无法在重渲染后恢复焦点。
  3. 状态同步方式问题:直接用register绑定第三方组件时,可能跟不上react-hook-form的状态更新节奏,尤其是表单校验状态变化触发重渲染时,焦点管理容易出问题。

解决办法

1. 确保自定义组件引用稳定

把EuiCellPhoneNumberFieldText定义在表单组件外部,或用useMemo缓存组件引用,避免每次重渲染创建新实例:

// 定义在外部,保证引用稳定
const EuiCellPhoneNumberFieldText = React.forwardRef((props, ref) => {
  return <input ref={ref} {...props} />;
});

// 或在表单组件内部用useMemo缓存
const MyForm = () => {
  const stableInputComponent = React.useMemo(() => EuiCellPhoneNumberFieldText, []);
  
  // ...其他表单逻辑
  return (
    <PhoneInputWithCountry
      inputComponent={stableInputComponent}
      // ...其他props
    />
  );
};

2. 正确传递Ref到底层输入框

检查EuiCellPhoneNumberFieldText的实现,确保forwardRef接收的ref绑定到真实的输入元素:

const EuiCellPhoneNumberFieldText = React.forwardRef(({ onChange, onBlur, ...rest }, ref) => {
  // 把ref传递给实际的输入组件
  return (
    <EuiFieldText
      ref={ref}
      onChange={(e) => onChange(e.target.value)}
      onBlur={onBlur}
      {...rest}
    />
  );
});

3. 用Controller包裹第三方组件

react-hook-form的Controller组件专门适配第三方表单控件,能更稳定地同步状态和管理焦点:

import { Controller, useForm } from 'react-hook-form';

const MyForm = () => {
  const { control, formState: { isValid } } = useForm({
    defaultValues: { cellPhoneNumber: '' }
  });

  return (
    <form>
      <Controller
        name="cellPhoneNumber"
        control={control}
        render={({ field: { onChange, value, ref } }) => (
          <PhoneInputWithCountry
            value={value}
            onChange={onChange}
            inputComponent={EuiCellPhoneNumberFieldText}
            ref={ref}
          />
        )}
      />
      <button type="submit" disabled={!isValid}>Save Changes</button>
    </form>
  );
};

4. 添加稳定的Key

给PhoneInputWithCountry或自定义输入组件添加固定key,帮助React识别组件身份,避免不必要的卸载/挂载:

<PhoneInputWithCountry
  key="cell-phone-input"
  inputComponent={EuiCellPhoneNumberFieldText}
  // ...其他props
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:31:18