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

Formik结合Yup与Semantic UI实现表单条件校验问题咨询

问题根源

现有校验规则对Facebook、Instagram的关联字段直接设置了全局必填,没有根据平台选中状态动态调整校验逻辑,同时组件存在表单状态重复维护、渲染判断不一致、漏加Instagram链接字段校验的问题,才会出现无论选不选对应平台都强制校验所有字段的情况。

修复方案

1. 重写Yup校验规则,用when实现条件校验

通过Yup内置的when方法监听平台选中字段的值,只有当对应平台被选中时,才启用关联字段的必填规则,修改后的校验代码如下:

import * as yup from 'yup';

export const ProfessionalValidation = yup.object().shape({
  // 分类字段保留原有必填规则
  category: yup.array().required('Category Name is required').nullable(),
  // 平台选择字段设置最少选1项的规则
  platform: yup.array().min(1, 'At least One Platform is required').required('At least One Platform is required').nullable(),
  
  // Facebook关联字段:仅当选中Facebook时才必填
  facebookLink: yup.string().when('platform', {
    is: (platform) => Array.isArray(platform) && platform.includes('Facebook'),
    then: (schema) => schema.required('Facebook account link is required'),
    otherwise: (schema) => schema.notRequired()
  }).nullable(),
  FBfollowers: yup.string().when('platform', {
    is: (platform) => Array.isArray(platform) && platform.includes('Facebook'),
    then: (schema) => schema.required('Please select your Facebook follower count'),
    otherwise: (schema) => schema.notRequired()
  }).nullable(),

  // Instagram关联字段:仅当选中Instagram时才必填
  InstaLink: yup.string().when('platform', {
    is: (platform) => Array.isArray(platform) && platform.includes('Instagram'),
    then: (schema) => schema.required('Instagram account link is required'),
    otherwise: (schema) => schema.notRequired()
  }).nullable(),
  Instafollowers: yup.string().when('platform', {
    is: (platform) => Array.isArray(platform) && platform.includes('Instagram'),
    then: (schema) => schema.required('Please select your Instagram follower count'),
    otherwise: (schema) => schema.notRequired()
  }).nullable(),
})

注意:原代码漏写了InstaLink字段的校验规则,上述代码已补全,同时修正了原提示文本的拼写错误。

2. 修复组件逻辑bug

原组件单独维护了selectedOptions本地状态,和Formik内部管理的values.platform状态重复,很容易出现状态不同步的问题,且Instagram模块的渲染判断逻辑和Facebook不一致,需要同步调整:

  • 删除冗余的selectedOptions、savedata本地状态,所有表单值统一交给Formik管理
  • 多选字段的初始值从空字符串改为空数组,避免调用数组方法时报错
  • 统一用values.platform判断平台是否选中,补全缺失的提交方法、Instagram链接字段的错误提示
    修改后的核心组件代码如下:
import { useState } from 'react';
import { ProfessionalValidation } from "./Validation";
import { ErrorMessage, Formik, Form, Field } from "formik";
import {
  categoryOptions,
  Platform,
  followers,
} from "./Data";
import { Dropdown } from "semantic-ui-react";
import "./style.css";
import "./styles.css";

const UserInfo = () => {
  const defaultValue = {
    category: [],
    platform: [],
    facebookLink: "",
    InstaLink: "",
    Instafollowers: "",
    FBfollowers: "",
    subscribers: "",
    youtube: ""
  };

  const handleSubmit = (values) => {
    console.log('表单提交值', values);
    // 此处编写提交逻辑
  }

  return (
    <Formik
      initialValues={defaultValue}
      validationSchema={ProfessionalValidation}
      onSubmit={handleSubmit}
    >
      {({ values, setFieldValue }) => (
        <Form>
          <section className="form-styling my-4">
            <div className="container">
              <div className="input-box2">
                <div>
                  <label htmlFor="category">Category*</label>
                  <Field
                    clearable
                    name="category"
                    fluid
                    multiple
                    search
                    selection
                    options={categoryOptions}
                    component={Dropdown}
                    placeholder="Select Category"
                    onChange={(_, { value }) => setFieldValue("category", value)}
                  />
                  <span style={{ color: "red" }}>
                    <ErrorMessage name="category" />
                  </span>
                </div>

                <div>
                  <label htmlFor="platform">Platform*</label>
                  <Field
                    clearable
                    name="platform"
                    fluid
                    multiple
                    search
                    selection
                    options={Platform}
                    placeholder="Select Platform"
                    component={Dropdown}
                    onChange={(_, { value }) => setFieldValue("platform", value)}
                  />
                  <span style={{ color: "red" }}>
                    <ErrorMessage name="platform" />
                  </span>
                  <span className="mt-3 d-block">Select at least 1</span>
                </div>
              </div>

              <div className="platform-box">
                <div>
                  {values.platform.includes("Facebook") ? (
                    <div>
                      <div className="platform-details">
                        <div>
                          <h5>Facebook</h5>
                        </div>
                        <div>
                          <Field
                            type="text"
                            name="facebookLink"
                            placeholder="Account Link"
                          />
                          <span className="text-danger">
                            <ErrorMessage name="facebookLink" />
                          </span>
                        </div>
                        <div>
                          <Field
                            className="label ui selection fluid dropdown"
                            clearable
                            name="FBfollowers"
                            fluid
                            search
                            selection
                            options={followers}
                            component={Dropdown}
                            placeholder="Select followers"
                            onChange={(_, { value }) => setFieldValue("FBfollowers", value)}
                          />
                          <span className="text-danger">
                            <ErrorMessage name="FBfollowers" />
                          </span>
                        </div>
                      </div>
                      <span>Verify the Followers in 2-3 Business Days</span>
                    </div>
                  ) : null}

                  {values.platform.includes("Instagram") ? (
                    <div>
                      <div className="platform-details">
                        <div>
                          <h5>Instagram</h5>
                        </div>
                        <div>
                          <Field
                            type="text"
                            name="InstaLink"
                            placeholder="Account Link"
                          />
                          <span className="text-danger">
                            <ErrorMessage name="InstaLink" />
                          </span>
                        </div>
                        <div>
                          <Field
                            className="label ui selection fluid dropdown"
                            clearable
                            name="Instafollowers"
                            fluid
                            search
                            selection
                            options={followers}
                            component={Dropdown}
                            placeholder="Select followers"
                            onChange={(_, { value }) => setFieldValue("Instafollowers", value)}
                          />
                          <span style={{ color: "red" }}>
                            <ErrorMessage name="Instafollowers" />
                          </span>
                        </div>
                      </div>
                      <span>Verify the Followers in 2-3 Business Days</span>
                    </div>
                  ) : null}
                </div>
              </div>
            </div>
          </section>

          <section className="additional-Info ">
            <div className="container">
              <div className="main-box"></div>
              <div className="text-start my-5">
                <button type="submit" className="border-0">
                  <span className="btn-form btn btn-info">Continue</span>
                </button>
              </div>
            </div>
          </section>
        </Form>
      )}
    </Formik>
  );
};

export default UserInfo;
最终效果
  • 未选中任何平台时,仅提示平台字段必填,不会触发平台关联字段的校验
  • 选中单个平台时,仅校验对应平台的账号链接、粉丝数字段,未选中平台的字段无校验要求
  • 同时选中多个平台时,所有选中平台的关联字段都触发必填校验
  • 取消选中某平台时,对应字段的校验规则自动移除,不会残留校验报错

内容的提问来源于stack exchange,提问作者kanu das

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:36:47