如何在React中结合Formik实现对象数组的单选与多选Autocomplete?
在React中结合Formik实现支持单选/多选的Autocomplete组件
下面是基于Material-UI Autocomplete和Formik实现单选/多选对象数组选择的完整方案,包含代码示例和关键逻辑说明:
核心实现代码
import { Formik, Form } from 'formik'; import { Autocomplete, TextField, Chip } from '@mui/material'; // 选项数据源 const arrayOfObject = [ { id: 1, name: "test" }, { id: 2, name: "test1" }, { id: 3, name: "test2" }, ]; // 表单组件 const MyForm = () => { return ( <Formik initialValues={{ userId: [] }} // 多选时初始值为数组,单选时设为null或单个ID onSubmit={(values) => { console.log('提交的表单值:', values); }} > {({ formik }) => ( <Form> <Autocomplete id="userId" multiple // 设为false则切换为单选模式 options={arrayOfObject} getOptionLabel={(option) => option.name} // 指定选项显示的文本 onChange={(event, newValue) => { // 多选时提取选中项的ID数组,单选时直接取单个ID const selectedIds = multiple ? newValue.map(item => item.id) : newValue?.id || null; formik.setFieldValue('userId', selectedIds); }} // 根据Formik字段值反向匹配对应的完整对象,保证组件显示与表单状态一致 value={ multiple ? arrayOfObject.filter(option => formik.values.userId.includes(option.id)) : arrayOfObject.find(option => option.id === formik.values.userId) || null } renderInput={(params) => ( <TextField {...params} label="食材" variant="outlined" inputProps={{ ...params.inputProps, 'aria-label': '选择食材', }} /> )} // 多选模式下自定义标签渲染 renderTags={(value, getTagProps) => value.map((option, index) => ( <Chip key={option.id} // 用唯一ID做key,避免index导致的渲染异常 label={option.name} {...getTagProps({ index })} /> )) } noOptionsText="未找到数据!" /> </Form> )} </Formik> ); }; export default MyForm;
关键逻辑说明
- 状态同步:通过
onChange事件将选中对象的ID(或ID数组)同步到Formik的表单字段,确保表单存储的是业务所需的ID值,而非完整对象。 - 值映射:
value属性通过Formik字段值反向匹配数据源中的完整对象,保证Autocomplete组件的显示值与表单状态完全对齐。 - 单选/多选切换:仅需修改
multiple属性,同时调整initialValues、onChange和value的逻辑即可切换模式:- 单选模式:设置
initialValues={{ userId: null }},onChange取newValue?.id,value用find匹配单个对象。 - 多选模式:设置
initialValues={{ userId: [] }},onChange取ID数组,value用filter匹配多个对象。
- 单选模式:设置
- 细节优化:渲染标签时使用对象的唯一
id作为key,避免因index变动导致的不必要重渲染。
内容的提问来源于stack exchange,提问作者mahesh chudasama
相关产品推荐
相关产品推荐

