努力让 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
的值为 true
或 false
.
但是,“With MUI”复选框表现出不同的行为。它不是设置 true
或 false
,而是创建一个数据数组。我知道这样做是为了处理组合在一起的多个复选框。但是,我看不到在将数组值传递给 MUI 复选框之前可以将该数组值转换为 true
或 false
的任何地方。看起来 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;
我无法让 Formik 5 和 MUI 5 复选框协同工作。在下面的 Codesandbox 中,您会看到一个带有两个未选中复选框的表单:“with MUI”和“without MUI”。
“没有 MUI”复选框的行为符合预期:我可以选中和取消选中它,如果我提交,我会在控制台中看到 withoutMui
的值为 true
或 false
.
但是,“With MUI”复选框表现出不同的行为。它不是设置 true
或 false
,而是创建一个数据数组。我知道这样做是为了处理组合在一起的多个复选框。但是,我看不到在将数组值传递给 MUI 复选框之前可以将该数组值转换为 true
或 false
的任何地方。看起来 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;