努力让 MaterialUI 5 复选框与 Formik 2 一起使用

Struggling to get MaterialUI 5 checkbox to work with Formik 2

我无法让 Formik 5 和 MUI 5 复选框协同工作。在下面的 Codesandbox 中,您会看到一个带有两个未选中复选框的表单:“with MUI”和“without MUI”。

“没有 MUI”复选框的行为符合预期:我可以选中和取消选中它,如果我提交,我会在控制台中看到 withoutMui 的值为 truefalse.

但是,“With MUI”复选框表现出不同的行为。它不是设置 truefalse,而是创建一个数据数组。我知道这样做是为了处理组合在一起的多个复选框。但是,我看不到在将数组值传递给 MUI 复选框之前可以将该数组值转换为 truefalse 的任何地方。看起来 Typescript 期望从 useField 返回的 field.checked 是布尔值而不是数组,所以我无法在不收到 Typescript 错误的情况下对该值进行任何操作。

有趣的是,如果我选中“with MUI”复选框一次,我会看到一个包含 1 个值 (on) 的数组。如果我再次单击复选框,则会得到一个没有值的数组,但复选框 UI 不会更新。所以看起来复选框数据已正确更新,但 MUI 复选框无法处理数组数据。

我觉得自己在做一些愚蠢的事情,希望能指出我的错误做法。

提前致谢!

https://codesandbox.io/s/wizardly-https-bb7up6

非 MUI 来自沙盒的复选框代码:

import { useField } from "formik";

const CheckboxWithoutMUI = ({ label, ...rest }) => {
  const [field, meta] = useField({ ...rest, type: "checkbox" });
  return (
    <div>
      <label>
        <input type="checkbox" {...field} {...rest} />
        {label}
      </label>
    </div>
  );
};

export default CheckboxWithoutMUI;

MUI 来自沙箱的复选框代码:

import { useField } from "formik";
import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox";

interface IProps {
  label: string;
  name: string;
}

const CheckboxField = ({ label, ...rest }: IProps) => {
  const [field, meta] = useField({ ...rest, type: "checkbox" });

  return (
    <div>
      <FormControlLabel
        label={label}
        control={
          <Checkbox
            checked={field.checked}
            onChange={field.onChange}
            id={field.name}
          />
        }
      />
    </div>
  );
};

export default CheckboxField;
Software Version(s)
Formik 2.2.9
React 17.0.2
TypeScript 4.5.5
Browser Chrome (Mac) 101.0.4951.64
npm/Yarn 8.5.0
Operating System macOS 12.4

两个复选框的行为差异是由于没有为 MUI 复选框提供 value。这导致 Formik 以不同方式管理复选框值。

如果您从 non-MUI 复选框中删除 value 道具,它的行为将与沙盒中的 MUI 复选框相同:

import { useField } from "formik";

const CheckboxWithoutMUI = ({ label, ...rest }) => {
  const [field, meta] = useField({ ...rest, type: "checkbox" });
  const { value, ...fieldExceptValue } = field;
  return (
    <div>
      <label>
        <input type="checkbox" {...fieldExceptValue} {...rest} />
        {label}
      </label>
    </div>
  );
};

export default CheckboxWithoutMUI;

如果您将 MUI 复选框的语法更改为更类似于您的 non-MUI 版本(将所有 field 道具传递给它),它会按预期工作:

import { useField } from "formik";
import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox";

interface IProps {
  label: string;
  name: string;
}

const CheckboxField = ({ label, ...rest }: IProps) => {
  const [field] = useField({ ...rest, type: "checkbox" });
  return (
    <div>
      <FormControlLabel label={label} control={<Checkbox {...field} />} />
    </div>
  );
};

export default CheckboxField;

value添加到您已有的内容中也足够了:

import { useField } from "formik";
import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox";

interface IProps {
  label: string;
  name: string;
}

const CheckboxField = ({ label, ...rest }: IProps) => {
  const [field] = useField({ ...rest, type: "checkbox" });

  return (
    <div>
      <FormControlLabel
        label={label}
        control={
          <Checkbox
            checked={field.checked}
            onChange={field.onChange}
            id={field.name}
            value={field.value}
          />
        }
      />
    </div>
  );
};

export default CheckboxField;