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

useEffect结合watch无法过滤表单字段变更的问题咨询

问题:react-hook-form中useEffect依赖[cityValue]无法过滤字段变更的原因

我尝试使用react-hook-form的watch hook监听city字段的变更,期望仅当city变化时触发日志输出,而name字段变更时不产生日志,但实际运行时所有表单字段变更都会触发日志,且useEffect的依赖[cityValue]未起到过滤作用,效果等同于依赖为空数组。

代码示例:

import * as React from 'react';
import { useForm } from 'react-hook-form';

export default function App() {
  const { watch, register } = useForm({
    mode: 'all',
    reValidateMode: 'onBlur',
  });

  const cityValue = watch('city', 'my city');
  const nameValue = watch('name', 'my name');

  // Will console the changes
  React.useEffect(() => {
    const subscription = watch((value, { name, type }) =>
      console.log(value, name, type)
    );
    return () => subscription.unsubscribe();
  }, [cityValue]);

  return (
    <div>
      <p>Start editing & look at the console how values changes :</p>
      <input value={cityValue} {...register('city')} />
      <label>{cityValue}</label> <br />
      <input value={nameValue} {...register('name')} />
      <label>{nameValue}</label> <br />
    </div>
  );
}

原因及解决方案

核心原因

你在useEffect中调用的是无参数的watch(),它会订阅所有表单字段的变更,和你设置的依赖[cityValue]无关:

  1. watch('city')返回的city字段值变化时,会触发useEffect重新执行,但每次执行都会创建一个新的全字段订阅,所以name字段变更时依然会触发日志。
  2. [cityValue]只是控制useEffect的执行时机,不是控制watch的监听范围。就算city变化后重新订阅,新订阅依然监听所有字段,达不到只监听city的目的。
  3. 当前写法还会导致重复订阅:每次city变化,旧订阅虽然被取消,但新订阅又会监听全字段,完全偏离需求。

正确写法

方法1:直接订阅指定字段

通过给watch()传入字段名,只监听city的变更,不需要依赖cityValue:

import * as React from 'react';
import { useForm } from 'react-hook-form';

export default function App() {
  const { watch, register } = useForm({
    mode: 'all',
    reValidateMode: 'onBlur',
  });

  const cityValue = watch('city', 'my city');
  const nameValue = watch('name', 'my name');

  React.useEffect(() => {
    // 仅订阅city字段的变更
    const subscription = watch('city', (value, { name, type }) => {
      console.log(value, name, type);
    });
    return () => subscription.unsubscribe();
  }, [watch]); // 依赖watch实例即可

  return (
    <div>
      <p>Start editing & look at the console how values changes :</p>
      <input value={cityValue} {...register('city')} />
      <label>{cityValue}</label> <br />
      <input value={nameValue} {...register('name')} />
      <label>{nameValue}</label> <br />
    </div>
  );
}

方法2:直接监听cityValue的变化

如果只是需要在city值变化时执行逻辑,不需要使用watch的订阅回调,直接监听cityValue即可:

import * as React from 'react';
import { useForm } from 'react-hook-form';

export default function App() {
  const { watch, register } = useForm({
    mode: 'all',
    reValidateMode: 'onBlur',
  });

  const cityValue = watch('city', 'my city');
  const nameValue = watch('name', 'my name');

  // 仅在cityValue变化时触发
  React.useEffect(() => {
    console.log('city changed:', cityValue);
  }, [cityValue]);

  return (
    <div>
      <p>Start editing & look at the console how values changes :</p>
      <input value={cityValue} {...register('city')} />
      <label>{cityValue}</label> <br />
      <input value={nameValue} {...register('name')} />
      <label>{nameValue}</label> <br />
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 06:30:45