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

React IMask手机号掩码与React Hook Form联动值更新异常求助

React Hook Form 搭配 IMask 手机号掩码值同步问题解决

问题描述

使用IMask实现手机号输入掩码功能,结合React Hook Form管理表单时出现值更新异常:输入1234567后,掩码显示123-45-67,但表单返回值不正确,控制台抛出提示:

Element value was changed outside of mask. Syncronize mask using mask.updateValue() to work properly.

尝试调用updateValue()同步但未成功,需提供正确实现方案。

原相关代码

主组件代码

const {handleSubmit, register, control, formState: { errors },} = useForm({
  resolver: yupResolver(schema),
});

const phoneInput = useMemo(
  () => (
    <PhoneMaskInput
      control={control}
      register={register}
      name="phone"
      inputName="Mobil nömrəniz"
      id="phone"
      placeholder="Mobil nömrə"
      required
      error={errors?.phone?.message}
    />
  ),
  [errors.phone],
);

<form onSubmit={handleSubmit(onSubmit)} noValidate>
      {phoneInput}
      <button type="submit">Daxil olun</button>
</form>

IMask组件代码

import { useRef } from 'react';
import { IMaskInput } from 'react-imask';
import { Controller } from 'react-hook-form';

const PhoneMaskInput = ({ control, name, inputName, placeholder }) => {
  const ref = useRef(null);
  const inputRef = useRef(null);

  return (
      <div className="input-container">
        <Controller
          name={name}
          control={control}
          defaultValue=""
          render={({ field }) => (
            <IMaskInput
              mask="000-00-00"
              placeholder={placeholder}
              unmask={true}
              ref={ref}
              {...field}
              classID={id}
              className="imask-input"
              inputRef={inputRef}
              onAccept={(value) => field.onChange(value)}
            />
          )}
        />
      </div>
  );
};

export default PhoneMaskInput;

修正后的实现方案

问题根源

  1. {...field}传入的React Hook Form原生onChange,与IMask的onAccept逻辑冲突,导致值同步混乱
  2. 未监听表单值的外部修改(如重置、初始化),无法同步到IMask输入框
  3. Ref绑定错误,无法获取IMask实例调用updateValue()完成同步

修正后的IMask组件代码

import { useRef, useEffect } from 'react';
import { IMaskInput } from 'react-imask';
import { Controller } from 'react-hook-form';

const PhoneMaskInput = ({ control, name, placeholder, error }) => {
  // 存储IMask实例的ref
  const maskRef = useRef(null);

  return (
    <div className="input-container">
      <Controller
        name={name}
        control={control}
        defaultValue=""
        render={({ field: { value, onChange, ref } }) => {
          // 监听表单值变化,同步到IMask输入框
          useEffect(() => {
            if (maskRef.current) {
              maskRef.current.updateValue(value);
            }
          }, [value]);

          return (
            <>
              <IMaskInput
                // 绑定IMask实例到maskRef
                ref={maskRef}
                // 挂载原生input的ref到React Hook Form的ref
                inputRef={ref}
                mask="000-00-00"
                placeholder={placeholder}
                unmask={true}
                className={`imask-input ${error ? 'error' : ''}`}
                // 仅通过IMask的onAccept更新表单值
                onAccept={(unmaskedValue) => onChange(unmaskedValue)}
              />
              {error && <span className="error-message">{error}</span>}
            </>
          );
        }}
      />
    </div>
  );
};

export default PhoneMaskInput;

主组件代码调整

const {handleSubmit, control, formState: { errors },} = useForm({
  resolver: yupResolver(schema),
});

// 修正useMemo依赖,添加control确保组件正确更新
const phoneInput = useMemo(
  () => (
    <PhoneMaskInput
      control={control}
      name="phone"
      placeholder="Mobil nömrə"
      error={errors?.phone?.message}
    />
  ),
  [control, errors.phone],
);

<form onSubmit={handleSubmit(onSubmit)} noValidate>
      {phoneInput}
      <button type="submit">Daxil olun</button>
</form>

关键优化点

  1. 分离Ref职责:maskRef存储IMask实例,inputRef绑定React Hook Form需要的原生input节点,避免逻辑冲突
  2. 统一值更新逻辑:仅通过IMask的onAccept回调更新表单值,消除重复触发问题
  3. 同步外部值修改:添加useEffect监听表单值变化,主动调用updateValue()同步到IMask输入框,解决控制台报错
  4. 修正依赖项:主组件useMemo添加control依赖,确保组件在表单控制实例变化时正确更新

内容的提问来源于stack exchange,提问作者Rahil Əliyev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 23:44:56