对于 Material-UI 字段,我有一个特殊的 TextField
包装器,它似乎运行良好。出于某种原因,当我使用原生 Material UI 字段时,它们不会在提交时更新表单数据。
这是相关的代码(但我在帖子末尾添加了一个代码沙箱以帮助演示该问题)
TestForm.tsx
import { Card, CardActions, CardContent } from "@material-ui/core";
import { Form, Formik, Field } from "formik";
import React from "react";
import SubmitButton from "../../SubmitButton";
import CancelButton from "../../CancelButton";
import TextField from "../../TextField";
import MuiTextField from "@material-ui/core/TextField";
interface TestFormProps {
onSave: (fields: FormFields) => void;
onCancel: () => void;
}
export interface FormFields {
textField: string;
numericField: number;
materialField: string;
materialFieldFromComponent: string;
}
const initialValues: FormFields = {
textField: "Default Text",
numericField: 42,
materialField: "Default Mui",
materialFieldFromComponent: "Default Mui from Component"
};
const TestForm: React.FC<TestFormProps> = ({ onCancel, onSave }) => {
return (
<Formik
initialValues={initialValues}
onSubmit={async (fields, { setSubmitting }) => {
setSubmitting(true);
onSave(fields);
}}
>
{({ isSubmitting }) => (
<Form>
<Card>
<CardContent>
<TextField name="textField" label="Text field" />
<TextField
name="numericField"
type="number"
label="Numeric field"
/>
<div>
<MuiTextField
name="materialField"
label="Mui field"
variant="outlined"
margin="dense"
/>
</div>
<Field
name="materialFieldFromComponent"
label="Mui field from Component"
variant="outlined"
margin="dense"
component={MuiTextField}
/>
</CardContent>
<CardActions>
<SubmitButton disabled={isSubmitting} />
<CancelButton onCancel={onCancel} />
</CardActions>
</Card>
</Form>
)}
</Formik>
);
};
export default TestForm;
TextField.tsx
import React from "react";
import { FieldAttributes, useField } from "formik";
import {
InputBaseComponentProps,
TextField as MuiTextField
} from "@material-ui/core";
interface TextFieldProps {
label: string;
inline?: boolean;
inputProps?: InputBaseComponentProps;
}
const Field: React.FC<FieldAttributes<TextFieldProps>> = (props) => {
const { type, label, placeholder, inputProps } = props;
const [field, meta] = useField<TextFieldProps>(props);
const errorText = meta.error && meta.touched ? meta.error : "";
return (
<MuiTextField
{...field}
label={label}
variant="outlined"
margin="dense"
type={type}
placeholder={placeholder ? placeholder : label}
helperText={errorText}
error={!!errorText}
inputProps={inputProps}
/>
);
};
const TextField: React.FC<FieldAttributes<TextFieldProps>> = ({
inline = false,
...props
}) => {
return inline ? (
<Field {...props} />
) : (
<div>
<Field {...props} />
</div>
);
};
export default TextField;
这是代码沙箱:
答案 0 :(得分:1)
这是因为您创建的 TextField
传递了正确的字段属性,而材质 UI 字段的其他直接实现则没有。
按如下方式传递正确的属性,即可解决问题:
{({ isSubmitting, handleChange, handleBlur, values }) => (
...
<div>
<MuiTextField
name="materialField"
label="Mui field"
variant="outlined"
margin="dense"
onChange={handleChange}
onBlur={handleBlur}
value={values.materialField}
/>
</div>
<Field
name="materialFieldFromComponent"
label="Mui field from Component"
variant="outlined"
margin="dense"
render={({ field }) => <MuiTextField {...field} />}
/>
...
MuiTextField
现在在其属性上传递了 onChange
和 values
,从而正确更新了值。
完整代码:TestForm.tsx
import { Card, CardActions, CardContent } from "@material-ui/core";
import { Form, Formik, Field } from "formik";
import React from "react";
import SubmitButton from "../../SubmitButton";
import CancelButton from "../../CancelButton";
import TextField from "../../TextField";
import MuiTextField from "@material-ui/core/TextField";
interface TestFormProps {
onSave: (fields: FormFields) => void;
onCancel: () => void;
}
export interface FormFields {
textField: string;
numericField: number;
materialField: string;
materialFieldFromComponent: string;
}
const initialValues: FormFields = {
textField: "Default Text",
numericField: 42,
materialField: "Default Mui",
materialFieldFromComponent: "Default Mui from Component"
};
const TestForm: React.FC<TestFormProps> = ({ onCancel, onSave }) => {
return (
<Formik
initialValues={initialValues}
onSubmit={async (fields, { setSubmitting }) => {
setSubmitting(true);
onSave(fields);
}}
>
{({ isSubmitting, handleChange, handleBlur, values }) => (
<Form>
<Card>
<CardContent>
<TextField name="textField" label="Text field" />
<TextField
name="numericField"
type="number"
label="Numeric field"
/>
<div>
<MuiTextField
name="materialField"
label="Mui field"
variant="outlined"
margin="dense"
onChange={handleChange}
onBlur={handleBlur}
value={values.materialField}
/>
</div>
<Field
name="materialFieldFromComponent"
label="Mui field from Component"
variant="outlined"
margin="dense"
render={({ field }) => <MuiTextField {...field} />}
/>
</CardContent>
<CardActions>
<SubmitButton disabled={isSubmitting} />
<CancelButton onCancel={onCancel} />
</CardActions>
</Card>
</Form>
)}
</Formik>
);
};
export default TestForm;