javascript - Formik och Material-UI
Jag försöker använda Formik med Material-UI-textfält. Så här:
import TextField from '@material-ui/core/TextField';
import {
Field,
FieldProps,
Form,
Formik,
FormikErrors,
FormikProps
} from 'formik';
import React, { Component } from 'react';
interface IMyFormValues {
firstName: string;
}
class CreateAgreementForm extends Component<{}> {
public render() {
return (
<div>
<h1>My Example</h1>
<Formik
initialValues={{ firstName: '' }}
// tslint:disable-next-line:jsx-no-lambda
onSubmit={(values: IMyFormValues) => alert(JSON.stringify(values))}
// tslint:disable-next-line:jsx-no-lambda
validate={(values: IMyFormValues) => {
const errors: FormikErrors<IMyFormValues> = {};
if (!values.firstName) {
errors.firstName = 'Required';
}
return errors;
}}
// tslint:disable-next-line:jsx-no-lambda
render={(formikBag: FormikProps<IMyFormValues>) => (
<Form>
<Field
name="firstName"
render={({ field, form }: FieldProps<IMyFormValues>) => (
<TextField
error={Boolean(
form.errors.firstName && form.touched.firstName
)}
helperText={
form.errors.firstName &&
form.touched.firstName &&
String(form.errors.firstName)
}
/>
)}
/>
</Form>
)}
/>
</div>
);
}
}
export default CreateAgreementForm;
Jag vill att Formik ska vara ansvarig för validering och Material-UI för utseendet. Jag vill skicka errors.firstName till TextField-komponenten men felet visas inte korrekt. Hur kan jag fixa det så att det fortfarande är tydligt att läsa? Jag vill inte skriva min egen TextField-komponent.
Svar #1
Jag tror inte att du behöver ett annat bibliotek eller ens skapa din egen wrapper, jag tror att du behöver justera din kod lite.
Ett problem du har är att du inte skickar in en onChange-funktion i Material TextField, så formulärvärdet för firstName är alltid null och därför får du alltid felet, även om du har angett ett namn. Försök att lägga till ett namn eller id på ditt TextField och en onChange-funktion så här:
<Field
validateOnBlur
validateOnChange
name="firstName"
render={({ field, form }) => (
<TextField
name={"firstName"}
error={
Boolean(form.errors.firstName && form.touched.firstName)
}
onChange={formikBag.handleChange}
onBlur={formikBag.handleBlur}
helperText={
form.errors.firstName &&
form.touched.firstName &&
String(form.errors.firstName)
}
/>
)}
/>
Svar #2
Som nämnts i kommentarerna kan det faktiskt vara en bra idé att implementera "wrapper"-komponenter, som de gjorde i dessa exempel från Formik eller ReactFinalForm :
- https://github.com/stackworx/formik-material-ui/tree/master/src
- https://github.com/final-form/react-final-form#material-ui-10
Idén är densamma: implementera egna "wrapper"-komponenter för att omsluta Material-UI-komponenter och mappa Formik- eller ReactFinalForm-API:ernas props.
Fördelarna med detta tillvägagångssätt är att centralisera kartläggningen mellan de två ramverken på ett ställe, så att du inte upprepar kartläggningen varje gång, och om ett av ramverken inför brytande förändringar behöver du bara ändra de anpassade "wrapper"-komponenterna.
