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
相关产品推荐
相关产品推荐

