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

如何用Formik验证绑定State值的可编辑表单?

问题分析

你遇到的核心问题是:Formik的Field组件依赖自身维护的表单状态做验证,但你手动用useState接管了字段的value和onChange,导致Formik内部状态与你的useState状态不同步,验证逻辑无法触发。

Formik的Yup验证是基于它自己追踪的表单值执行的,而你提交的是useState里的firstName,但Formik根本没感知到这个值的变化,自然不会执行验证。


解决方案

推荐两种处理方式,优先选第一种,更符合Formik的设计逻辑:

方式1:让Formik全权管理表单状态(推荐)

放弃手动维护useState,改用Formik的useFormik钩子统一处理值、验证和提交逻辑,代码更简洁且验证自动生效:

import { useFormik } from 'formik';
import * as Yup from 'yup';
import TextField from '@mui/material/TextField'; // 假设你用的是MUI TextField

// 初始化Formik实例
const formik = useFormik({
  initialValues: {
    first_name: currentUserDetails.first_name || '' // 从API数据初始化
  },
  validationSchema: Yup.object().shape({
    first_name: Yup.string().required("First Name is required.")
  }),
  onSubmit: (values) => {
    // 这里直接用验证后的values提交PUT请求
    console.log('待提交数据:', values);
    // 调用你的PUT接口:api.updateUser(values)
  }
});

// 渲染表单字段
return (
  <form onSubmit={formik.handleSubmit}>
    <TextField
      value={formik.values.first_name}
      onChange={formik.handleChange}
      onBlur={formik.handleBlur} // 触发" touched "状态,显示错误提示
      label="First Name"
      name="first_name"
      placeholder="Enter First Name"
      fullWidth
      size="small"
      error={formik.touched.first_name && Boolean(formik.errors.first_name)}
      helperText={formik.touched.first_name && formik.errors.first_name}
      required
    />
    <button type="submit">保存</button>
  </form>
);

方式2:手动同步useState与Formik状态(不推荐,仅兼容现有代码)

如果一定要保留useState,需要手动将firstName同步到Formik的内部状态,确保验证逻辑能感知到值的变化:

  1. 确保组件在Formik上下文内(比如包裹在<Formik>组件中),能拿到Formik的setFieldValue方法
  2. 修改Field的onChange,同步两个状态:
<Field
  onChange={(e, formikProps) => {
    const newValue = e.target.value;
    setFirstName(newValue); // 更新你的useState
    formikProps.setFieldValue('first_name', newValue); // 同步到Formik状态
  }}
  as={TextField}
  value={firstName || ""}
  label="First Name"
  name="first_name"
  placeholder="Enter First Name"
  fullWidth
  size="small"
  error={props.touched.first_name && Boolean(props.errors.first_name)}
  helperText={<ErrorMessage name="first_name" />}
  required
/>
  1. 初始化时同步初始值:
import { useEffect } from 'react';

useEffect(() => {
  props.setFieldValue('first_name', currentUserDetails.first_name || '');
}, [currentUserDetails, props.setFieldValue]);
  1. 提交时使用Formik的values(而非你的firstName):
const data = { first_name: props.values.first_name };

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 06:06:17