MUI表单报错:FormControl内存在多个InputBase组件,求解决方案
解决MUI表单中"There are multiple InputBase components inside a FormControl"错误
错误详情
完整错误提示:一个FormControl组件内包含了多个
InputBase组件,这会导致视觉不一致,请仅使用一个InputBase。
我正在开发一个借用事务React表单,使用MUI组件库与react-hook-form进行表单管理。最初将多个Select组件嵌套在单个FormControl中触发该错误,尝试移除Controller组件并拆分FormControl后问题仍未解决,希望修改代码消除错误。
问题原因
MUI的FormControl是为单个表单控件设计的容器,每个Select、TextField这类组件内部都封装了InputBase。第二次修改虽然拆分了一个FormControl,但第一个FormControl里仍然包含两个Select,违反了MUI的设计规范,所以错误依旧存在。另外,直接用Typography做标签不符合MUI表单结构要求,应该用InputLabel配合FormControl实现正确的标签关联。
修复后的代码
推荐保留react-hook-form的Controller组件,它能更简洁地实现MUI组件和表单状态的绑定,同时给每个Select单独配置FormControl:
import React, { useEffect } from "react"; import { LocalizationProvider } from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import { useForm, Controller } from "react-hook-form"; import { MenuItem, Typography, Select, FormControl, InputLabel, Button, Box } from "@mui/material"; import InnerContainer from "./InnerContainer"; const offices = [ { value: "building", label: "Building Management Office" }, { value: "information", label: "Information Technology Resource Office" }, { value: "engineering", label: "Engineering and Science Laboratory Office" }, ]; const itemsByOffice = { building: ["Spalding Basketball", "Mikasa Volleyball"], information: ["Nikon D300", "Profoto B10 Plus Strobe Lights"], engineering: ["Pyrex Beaker", "Pyrex Graduated Cycliner"], }; const endorser = [ { value: "211", label: "Ms. Roselle Wednesday Gardon" }, { value: "212", label: "Sir. Jojo Castillo" }, { value: "213", label: "Ms. Maryjane Lopez" }, { value: "214", label: "Ms. Mary Ann Gomez" }, { value: "215", label: "Ms. Maryjoy Padua" }, ]; const BorrowForm = () => { const { control, handleSubmit, watch } = useForm(); const selectedOffice = watch("offices"); const onSubmit = (data) => { console.log("submit hit with data:", data); }; useEffect(() => { console.log("Selected Office changed to:", selectedOffice); }, [selectedOffice]); return ( <InnerContainer> <LocalizationProvider dateAdapter={AdapterDayjs}> <Typography variant="h4" sx={{ mb: 3 }}>Borrowing Transaction</Typography> <Box sx={{ display: "flex", gap: 2, mb: 3 }}> {/* 第一个Select:Endorsed By */} <FormControl fullWidth variant="outlined"> <InputLabel>Endorsed By</InputLabel> <Controller name="endorser" control={control} defaultValue={endorser[0].value} render={({ field }) => ( <Select {...field} label="Endorsed By"> {endorser.map((option) => ( <MenuItem key={option.value} value={option.value}> {option.label} </MenuItem> ))} </Select> )} /> </FormControl> {/* 第二个Select:Office */} <FormControl fullWidth variant="outlined"> <InputLabel>Office</InputLabel> <Controller name="offices" control={control} defaultValue="" render={({ field }) => ( <Select {...field} label="Office"> {offices.map((office) => ( <MenuItem key={office.value} value={office.value}> {office.label} </MenuItem> ))} </Select> )} /> </FormControl> </Box> {/* 第三个Select:Equipment Name */} <FormControl fullWidth variant="outlined" sx={{ mb: 3 }}> <InputLabel>Equipment Name</InputLabel> <Controller name="items" control={control} defaultValue="" render={({ field }) => ( <Select {...field} label="Equipment Name" disabled={!selectedOffice}> {itemsByOffice[selectedOffice]?.map((item) => ( <MenuItem key={item} value={item}> {item} </MenuItem> ))} </Select> )} /> </FormControl> <Button type="submit" variant="contained" color="primary" onClick={handleSubmit(onSubmit)} > Submit </Button> </LocalizationProvider> </InnerContainer> ); }; export default BorrowForm;
关键修改点
- 每个
Select都被单独的FormControl包裹,确保一个FormControl对应一个表单控件 - 使用
InputLabel替代Typography作为表单标签,符合MUI表单结构规范,解决标签与控件的关联问题 - 保留
Controller组件,简化表单状态管理逻辑 - 添加
Box组件实现表单控件横向布局,提升视觉体验 - 给Equipment Name的Select添加
disabled属性,未选择Office时禁用,优化交互
内容的提问来源于stack exchange,提问作者notyouraveragetoru
相关产品推荐
相关产品推荐

