使用useFormik Hook时如何动态更新validationSchema?
动态设置Formik的validationSchema解决方案
问题原因
直接修改formik.validationSchema是错误用法,useFormik返回的实例属性并非响应式,Formik无法感知这种直接赋值的变化,因此验证逻辑不会生效。
最优实现模式
通过React状态管理validationSchema,结合Formik的enableReinitialize配置,实现动态更新验证规则。具体步骤如下:
- 用
useState初始化验证规则和表单初始值 - 在
useEffect中发起API请求,获取JSON Schema后生成Yup验证规则,同时按需更新表单初始值 - 将状态中的
validationSchema和initialValues传入useFormik,开启enableReinitialize允许Formik在依赖变化时重新初始化
代码示例:
import { useFormik } from 'formik'; import { useState, useEffect } from 'react'; import buildYup from 'schema-to-yup'; function DynamicSchemaForm() { const [validationSchema, setValidationSchema] = useState(null); const [initialValues, setInitialValues] = useState({}); useEffect(() => { // 模拟API请求获取JSON Schema fetch('/api/json-schema') .then(res => res.json()) .then(schemaData => { // 生成Yup验证规则 const yupSchema = buildYup(schemaData); setValidationSchema(yupSchema); // 根据Schema生成对应初始值(可根据实际需求调整默认值逻辑) const generatedInitialValues = Object.entries(schemaData.properties).reduce((acc, [key, prop]) => { acc[key] = prop.default ?? ''; return acc; }, {}); setInitialValues(generatedInitialValues); }); }, []); const formik = useFormik({ initialValues, validationSchema, enableReinitialize: true, // 关键配置:允许依赖变化时重新初始化Formik onSubmit: (values) => { alert(JSON.stringify(values, null, 2)); } }); // 未获取到Schema时显示加载状态 if (!validationSchema) { return <div>加载表单配置中...</div>; } return ( <form onSubmit={formik.handleSubmit}> {/* 根据动态生成的初始值渲染表单控件 */} {Object.keys(initialValues).map(fieldName => ( <div key={fieldName} className="form-group"> <label htmlFor={fieldName}>{fieldName}</label> <input id={fieldName} name={fieldName} type="text" value={formik.values[fieldName]} onChange={formik.handleChange} onBlur={formik.handleBlur} /> {/* 显示验证错误 */} {formik.touched[fieldName] && formik.errors[fieldName] && ( <div className="error">{formik.errors[fieldName]}</div> )} </div> ))} <button type="submit">提交</button> </form> ); }
针对你的问题逐一解答
是否错误使用了useFormik?
是的,直接修改formik.validationSchema不符合Formik的响应式设计,Formik无法追踪这种变化,导致验证失效。是否有更优的实现模式?
上述状态驱动+enableReinitialize的方式就是最优解,既符合React状态管理逻辑,也能让Formik正确感知验证规则的变化。是否只有暴露setValidationSchema函数才能实现该需求?
不需要。通过状态管理结合enableReinitialize配置,完全可以实现动态更新验证规则的需求,无需额外的setValidationSchema方法。
内容的提问来源于stack exchange,提问作者buildxyz
相关产品推荐
相关产品推荐

