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

Formik配合Material UI多选Autocomplete删除选中值后校验失效如何解决

问题根因
  • 多选模式下的Autocomplete清空所有选项时,返回的回调值是空数组[],而非你代码中判断的null。此时JSON.stringify([])会得到非空字符串"[]",自然无法触发你配置的字符串非空校验规则
  • 调用setFieldValue时没有同步标记字段为已触碰(touched),导致字段值修改后校验状态无法同步渲染到输入框提示上
优化实现方案

更推荐直接用数组格式存储多选结果,无需序列化转字符串,Yup原生支持数组类型校验,逻辑更简洁,完整修正代码如下:

import React from "react";
import { Formik, Form } from "formik";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import Button from "@material-ui/core/Button";
import * as Yup from 'yup';

const cities = [{
  state: "Illinois",
  name: "Chicago",
  id: 3,
}, {
  state: "Texas",
  name: "Houston",
  id: 2
}, {
  state: "California",
  name: "Los Angeles",
  id: 1
}, {
  state: "New York",
  name: "New York City",
  id: 4
}];

// 初始值改为空数组
const initialValues = {
  city_id: [],
};

// 提交时直接拿数组即可,无需反序列化
const submit = values => {
  const selectedCities = values.city_id;
  console.log('选中的城市:', selectedCities);
};

const SignupForm = () => {
  return (
    <Formik 
      initialValues={initialValues}
      // 校验规则改为数组类型,要求至少选1项
      validationSchema = {
        Yup.object().shape({
          city_id: Yup.array().min(1, 'City is required').required('City is required')
        })
      }
      onSubmit={submit}
    >
      {({ touched, errors, setFieldValue }) => (
        <Form>
          <Autocomplete
            multiple
            id="city_id"
            name="city_id"
            options={cities}
            getOptionLabel={option => option.name}
            style={{ width: 300 }}
            onChange={(e, value) => {
              // setFieldValue第三个参数传true,自动标记字段为touched,触发校验更新
              setFieldValue("city_id", value, true);
            }}
            renderInput={params => (
              <TextField
                error={Boolean(touched.city_id && errors.city_id)}
                helperText={touched.city_id && errors.city_id}
                margin="normal"
                label="Cities"
                fullWidth
                name="city_id"
                {...params}
              />
            )}
          />
          <Button variant="contained" color="primary" type="submit">
            Submit
          </Button>
        </Form>
      )}
    </Formik>
  );
}
export default SignupForm;

如果一定要保留序列化字符串的存储逻辑,只需修改onChange中的判断条件即可:

onChange={(e, value) => {
  const val = value.length ? JSON.stringify(value) : initialValues.city_id;
  setFieldValue("city_id", val, true);
}}

内容的提问来源于stack exchange,提问作者JUBED ALAM

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 09:12:03