如何在动态构建Yup Schema完成后条件式调用useForm?
动态构建Yup Schema配合useForm的正确姿势
核心问题拆解
你现在卡在两个关键点:一是违反React Hook调用规则(不能在条件分支后调用Hook),二是Schema更新后useForm校验逻辑的同步问题,还有null传入resolver直接报错的坑。
直接可行的解决方案
把useForm移到组件顶层,给resolver加兜底逻辑,再通过监听Schema变化重置表单:
function myHook() { const [mySchema, setMySchema] = useState<AnyObjectSchema | null>(null); useEffect(() => { // 替换为实际后端请求逻辑 const fetchSchema = async () => { const res = await fetch('/api/form-definition'); const schemaConfig = await res.json(); // 根据后端配置构建Yup Schema,示例逻辑按需调整 const newSchema = yup.object().shape(schemaConfig); setMySchema(newSchema); }; fetchSchema(); }, []); // 顶层无条件调用useForm,解决Hook规则问题 const { handleSubmit, register, reset } = useForm({ // 兜底:Schema未加载时返回空校验,避免报错 resolver: mySchema ? yupResolver(mySchema) : () => Promise.resolve({ values: {}, errors: {} }), defaultValues: {} // 按需设置表单默认值 }); // 当Schema更新时,重置表单让新校验规则生效 useEffect(() => { if (mySchema) { reset(); } }, [mySchema, reset]); if (!mySchema) { return <SkeletonForm />; } return <TheFormGoesHere register={register} handleSubmit={handleSubmit} />; }
关键细节说明
- 兜底Resolver:没拿到Schema时,返回一个永远成功的校验结果,既避免
yupResolver因null报错,也符合useForm的参数要求。 - Schema更新同步:useForm的resolver变化不会自动触发重新校验,所以用
useEffect监听mySchema变化,调用reset重置表单,强制应用新规则。 - Hook合规性:
useForm在组件最顶层调用,完全符合React Hook的调用规则,不会出现控制台警告。
额外小技巧
- 骨架屏阶段把表单提交按钮设为禁用状态,防止用户误操作。
- 构建Schema时加
try-catch,避免后端返回的配置异常导致页面崩溃。
内容的提问来源于stack exchange,提问作者Garrett
相关产品推荐
相关产品推荐

