基于Formik的MUI多选Select组件提交异常及显示问题求助
解决Formik中MUI多选Select的取值与显示问题
你当前的核心问题是Formik表单状态和MUI组件状态脱节:原代码维护了独立的personName状态,导致提交时Formik无法获取选中值;改成绑定Formik的values.usersId后,又因为Checkbox的判断逻辑没同步调整,导致选中状态不显示。下面是完整的修正方案:
修正后的完整代码
/*(...)*/ // 你的Schema和初始值定义是正确的,数组类型校验符合需求 const projectSchema = yup.object().shape({ usersId: yup.array().of(yup.string()), }); const initialValuesProject = { usersId: [], }; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { style: { maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, width: 250, }, }, }; const Calendar = () => { // 移除多余的personName独立状态,完全复用Formik的表单状态 const { data } = useGetAllUsersQuery(); /*(...)*/ return ( /*(...)*/ <Formik onSubmit={handleFormSubmit} initialValues={initialValuesProject} validationSchema={projectSchema} > {/* 解构Formik提供的核心方法 */} {({ values, handleSubmit, setFieldValue }) => ( <form onSubmit={handleSubmit}> <FormControl size="small" sx={{ m: 1 }}> <Select id="encargadoP" multiple // 直接绑定Formik的表单字段值 value={values.usersId} // 自定义onChange,用setFieldValue同步更新Formik状态 onChange={(event) => { const { value } = event.target; // 保留自动填充的字符串处理逻辑 const selectedValues = typeof value === "string" ? value.split(",") : value; setFieldValue("usersId", selectedValues); }} MenuProps={MenuProps} renderValue={(selected) => selected.join(", ")} sx={{ width: 205 }} > {data?.map(({ _id, name }) => ( <MenuItem key={_id} value={name}> {/* 基于Formik的values判断选中状态 */} <Checkbox checked={values.usersId.includes(name)} /> <ListItemText primary={name} /> </MenuItem> ))} </Select> </FormControl> </form> )} </Formik> ); }; export default Calendar;
关键修改说明
- 移除独立状态:删掉
personName相关的useState和自定义handleChange,不再维护组件内部的独立状态,完全依赖Formik的values.usersId - 绑定Formik字段:Select的
value直接设为values.usersId,确保组件显示内容和Formik表单状态完全一致 - 同步更新Formik状态:在Select的
onChange中使用Formik提供的setFieldValue方法更新usersId字段,同时保留自动填充的字符串处理逻辑 - 修正选中判断:Checkbox的
checked属性改为判断values.usersId.includes(name),确保选中状态和Formik的表单值同步
额外优化建议
如果业务需要存储用户的_id而非name(更规范的后端交互做法),只需要做两处调整:
- 将MenuItem的value改为
_id:<MenuItem key={_id} value={_id}> - 渲染选中值时根据
_id映射回用户名:renderValue={(selectedIds) => selectedIds.map(id => data.find(user => user._id === id)?.name).join(", ") }
内容的提问来源于stack exchange,提问作者Valentina Loaiza
相关产品推荐
相关产品推荐

