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

如何在react-hook-form中监听表单重置事件?

解决方案

针对react-hook-form中子组件监听表单重置并同步非注册字段状态的需求,有两种可靠方案:

方案一:自定义上下文传递重置信号

通过创建专属Context,让父组件在触发表单重置时主动通知子组件执行额外操作,这是最直观且无副作用的方案:

修改后的完整代码

import { useState, createContext, useEffect } from 'react';
import { FormProvider, useForm, useFormContext } from 'react-hook-form';

// 创建重置上下文,用于传递触发信号
const ResetContext = createContext();

const initialValues = { firstName: "empty", lastName: "empty" };
function MyForm() {
    const methods = useForm({ defaultValues: { ...initialValues } });
    // 用数值递增作为触发信号,确保每次重置都能触发子组件的监听
    const [resetTrigger, setResetTrigger] = useState(0);

    const onSubmit = data => {
        console.log(data);
    };

    const handleReset = () => {
        // 先执行react-hook-form的表单重置
        methods.reset({ ...initialValues });
        // 更新触发信号,通知子组件同步状态
        setResetTrigger(prev => prev + 1);
    };

    return (
        <ResetContext.Provider value={resetTrigger}>
            <FormProvider {...methods}>
                <CustomContent />
                <button type="button" onClick={methods.handleSubmit(onSubmit)}>Submit</button>
                <button type="button" onClick={handleReset}>Reset</button>
            </FormProvider >
        </ResetContext.Provider>
    );
}

function CustomContent() {
    const { register } = useFormContext();
    const resetTrigger = useContext(ResetContext);
    const [isChecked, setIsChecked] = useState(false);

    // 监听重置信号,触发复选框状态重置
    useEffect(() => {
        setIsChecked(false);
    }, [resetTrigger]);

    return (
        <div>
            <input {...register('firstName')} placeholder="First Name" />
            <input {...register('lastName')} placeholder="Last Name" />
            <label >
                <input type="checkbox" checked={isChecked} onChange={() => setIsChecked((prev) => !prev)} />
                <span>Check me</span>
            </label>
        </div>
    );
}

export default MyForm;

方案二:全局自定义事件(轻量备选)

如果不想新增Context,可以利用浏览器自定义事件实现跨组件通知,适合简单场景:

修改父组件的重置逻辑

const handleReset = () => {
    methods.reset({ ...initialValues });
    // 派发全局自定义事件
    window.dispatchEvent(new CustomEvent('form-reset'));
};

子组件监听事件

function CustomContent() {
    const { register } = useFormContext();
    const [isChecked, setIsChecked] = useState(false);

    useEffect(() => {
        const handleReset = () => setIsChecked(false);
        // 监听自定义事件
        window.addEventListener('form-reset', handleReset);
        // 组件卸载时移除监听
        return () => window.removeEventListener('form-reset', handleReset);
    }, []);

    // ... 其余代码不变
}

为什么基于isDirty的方案无效

你之前尝试的isDirty监听方案存在两个问题:

  1. 若表单从未被修改过,点击重置时isDirty始终为false,不会触发useEffect;
  2. 若用户手动将表单字段改回初始值,isDirty也会变为false,这会误触发复选框重置,不符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 22:30:01