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

使用useFormik Hook时如何动态更新validationSchema?

动态设置Formik的validationSchema解决方案

问题原因

直接修改formik.validationSchema是错误用法,useFormik返回的实例属性并非响应式,Formik无法感知这种直接赋值的变化,因此验证逻辑不会生效。

最优实现模式

通过React状态管理validationSchema,结合Formik的enableReinitialize配置,实现动态更新验证规则。具体步骤如下:

  1. 用useState初始化验证规则和表单初始值
  2. 在useEffect中发起API请求,获取JSON Schema后生成Yup验证规则,同时按需更新表单初始值
  3. 将状态中的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:15:28