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

如何将Material UI多选Select组件与Formik集成?

解决Material UI多选Select与Formik集成时无法获取选中值的问题

你的核心问题是没有将Select的选中状态与Formik的表单状态同步,同时存在Select值类型不匹配的问题,导致Formik无法追踪选中内容。以下是具体修正方案:

问题分析

  1. 你用React本地state(personName)管理选中项,但Formik的values完全独立于这个本地状态,提交时自然拿不到数据。
  2. Select的value是对象数组,但MenuItem的value是字符串(FullName),类型不匹配会导致MUI的Select内部状态异常。
  3. 自定义的handleChange仅更新本地state,未同步到Formik的字段值。

修正步骤

  1. 移除本地state,改用Formik的initialValues初始化选中项
  2. 统一Select和MenuItem的value类型(建议用用户id,更高效且避免重名问题)
  3. 修改handleChange逻辑,直接通过Formik的setFieldValue更新表单字段
  4. 调整Select的renderValue和MenuItem渲染,匹配value类型

完整修正代码

import {
  FormControl,
  InputLabel,
  ListItemText,
  MenuItem,
  OutlinedInput,
  Select,
  Button,
} from '@mui/material';
import React from 'react';
import { Formik } from 'formik';

export default function Notifications() {
  const usersList = [
    { id: 1, FullName: 'Name1' },
    { id: 2, FullName: 'Name2' },
    { id: 3, FullName: 'Name3' },
    { id: 4, FullName: 'Name4' },
    { id: 5, FullName: 'Name5' },
  ];

  // 初始选中项的id数组,对应Formik的initialValues
  const initialSelectedIds = [2, 4];

  const submit = values => {
    // 可以根据id数组获取完整用户对象,或者直接提交id数组
    const selectedUsers = usersList.filter(u => values.selectedUsers.includes(u.id));
    console.log('选中的用户对象:', selectedUsers);
    console.log('Formik values:', values);
  };

  const handleChange = (event, setFieldValue) => {
    // event.target.value是选中的id数组(因为MenuItem的value设为了id)
    setFieldValue('selectedUsers', event.target.value);
  };

  return (
    <Formik 
      initialValues={{ selectedUsers: initialSelectedIds }}
      onSubmit={submit}
    >
      {({ values, setFieldValue }) => (
        <div>
          <FormControl sx={{ m: 1, width: 210 }} size="small">
            <InputLabel id="demo-multiple-checkbox-label">Users</InputLabel>
            <Select
              labelId="demo-multiple-checkbox-label"
              id="demo-multiple-checkbox"
              multiple
              // 用Formik的values作为Select的value,类型是id数组
              value={values.selectedUsers}
              // 把setFieldValue传给handleChange
              onChange={(e) => handleChange(e, setFieldValue)}
              input={<OutlinedInput label="Users" />}
              renderValue={(selectedIds) => {
                // 根据id数组渲染选中的用户名
                return selectedIds.map((id, index) => (
                  <span key={index} style={{ marginRight: 8 }}>
                    {usersList.find(u => u.id === id).FullName}
                  </span>
                ));
              }}
            >
              {usersList.map((user) => (
                <MenuItem key={user.id} value={user.id}>
                  <ListItemText primary={user.FullName} />
                </MenuItem>
              ))}
            </Select>
            <Button variant="contained" color="primary" type="submit">
              Submit
            </Button>
          </FormControl>
        </div>
      )}
    </Formik>
  );
}

关键说明

  • Formik初始化:通过initialValues设置初始选中的用户id数组,替代原来的本地state。
  • 值类型统一:MenuItem的value设为用户id(数字类型),Select的value对应Formik中的id数组,避免类型不匹配问题。
  • 状态同步:handleChange直接调用Formik的setFieldValue更新selectedUsers字段,确保Formik能追踪选中状态。
  • 渲染优化:renderValue根据id数组获取对应的用户名,渲染更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:37:02