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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:14:50