Next.js13+TS环境中React Hook Form的watch/useWatch类型错误排查
Next.js 13 + React Hook Form 7 + TypeScript 中 watch/useWatch 类型不匹配问题
问题背景
使用 Next.js 13、React Hook Form 7 和 TypeScript 开发时,调用 watch 钩子出现参数类型不匹配错误,即使将 tsconfig.json 中的 strict 设置为 false 也无法解决,useWatch 钩子同样存在该问题。
相关代码
watch 示例代码
import React from "react"; import { useForm } from "react-hook-form"; interface IFormInputs { name: string; showAge: boolean; age: number; } function App() { const { register, watch, formState: { errors }, handleSubmit, } = useForm<IFormInputs>(); const watchShowAge = watch("showAge", false); // 提供默认值作为第二个参数 const watchAllFields = watch(); // 不传参数时监听所有字段 const watchFields = watch(["showAge", "age"]); // 指定监听特定字段 // watch 的回调版本,需自行在组件卸载时取消订阅 React.useEffect(() => { const subscription = watch((value, { name, type }) => console.log(value, name, type)); return () => subscription.unsubscribe(); }, [watch]); const onSubmit = (data: IFormInputs) => console.log(data); return ( <> <form onSubmit={handleSubmit(onSubmit)}> <input {...register("name", { required: true, maxLength: 50 })} /> <input type="checkbox" {...register("showAge")} /> {/* 根据选择显示年龄输入框 */} {watchShowAge && <input type="number" {...register("age", { min: 50 })} />} <input type="submit" /> </form> </> ); }
useWatch 示例代码
import * as React from "react"; import { useForm, useWatch, Control } from "react-hook-form"; interface FormInputs { firstName: string; } function FirstNameWatched({ control }: { control: Control<FormInputs> }) { const firstName = useWatch({ control, name: "firstName", // 不传 name 则监听整个表单,或传入数组监听多个字段 defaultValue: "default" // 渲染前的默认值 }); return <p>Watch: {firstName}</p>; // 仅当 firstName 变化时组件重新渲染 } function App() { const { register, control, handleSubmit } = useForm<FormInputs>(); const onSubmit = (data: FormInputs) => { alert(JSON.stringify(data)); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <label>First Name:</label> <input {...register("firstName")} /> <input type="submit" /> <FirstNameWatched control={control} /> </form> ); }
错误信息
useWatch 对应的类型错误提示
Argument type {defaultValue: string, name: string, control: Control<FormInputs>} is not assignable to parameter type {defaultValue?: DeepPartialSkipArrayKey<DeepPartial<FormInputs>>, control?: Control<DeepPartial<FormInputs>>, disabled?: boolean, exact?: boolean}
解决方案
这类类型不匹配问题通常由依赖版本不一致、类型推导异常导致,可按以下步骤修复:
统一依赖版本:确保安装的
react-hook-form版本与官方示例一致,执行命令重新安装稳定版本:npm install react-hook-form@7.45.2正确传递 Control 类型:避免手动声明错误的
Control类型,直接从useForm的返回值中推导:function FirstNameWatched({ control }: { control: ReturnType<typeof useForm<FormInputs>>["control"] }) { const firstName = useWatch({ control, name: "firstName", defaultValue: "default" }); return <p>Watch: {firstName}</p>; }显式指定泛型参数:调用
useWatch时显式传入泛型,帮助 TypeScript 正确推导类型:const firstName = useWatch<FormInputs, "firstName">({ control, name: "firstName", defaultValue: "default" });优化 TypeScript 配置:调整
tsconfig.json中的类型相关配置,确保兼容性:{ "compilerOptions": { "strictNullChecks": false, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "lib": ["DOM", "DOM.Iterable", "ESNext"] } }清除缓存重启服务:Next.js 缓存可能导致类型推导异常,执行命令清除缓存后重启开发服务器:
rm -rf .next node_modules/.cache npm run dev
内容的提问来源于stack exchange,提问作者Xiang Liu
相关产品推荐
相关产品推荐

