Formik и Material-UI
Я пытаюсь использовать Formik с текстовым полем Material-UI. Вот так:
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;
Я хочу, чтобы Formik отвечал за валидацию и Material-UI за внешний вид.
Я хочу передать error.firstName компоненту TextField, но ошибка не отображается правильно. Как я могу это исправить, чтобы было понятно? Я не хочу писать свой собственный компонент TextField.
Ответы
Ответ 1
Как упомянуто в комментариях, на самом деле может быть хорошей идеей реализовать компоненты-оболочки, как они это делали в следующих примерах из Formik или ReactFinalForm:
Идея та же: реализовать пользовательские компоненты-обертки, чтобы обернуть компоненты Material-UI и отобразить реквизиты API Formik или ReactFinalForm.
Преимущества этого подхода состоят в том, чтобы централизовать в одном месте отображение между двумя платформами, чтобы вы не повторяли отображение каждый раз, и если одна из структур вносит критические изменения, вам просто нужно изменить эти пользовательские компоненты-оболочки.
Ответ 2
Я не думаю, что вам нужна другая библиотека или даже создать свою собственную оболочку, я думаю, вам нужно немного подправить свой код.
Одна из проблем заключается в том, что вы не передаете функцию onChange в Material TextField, поэтому значение формы firstName всегда равно null, и поэтому вы всегда получаете ошибку, даже если вы ввели имя. Попробуйте добавить имя или идентификатор в свой TextField и функцию onChange следующим образом:
<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)
}
/>
)}
/>
Ответ 3
Вы можете попробовать это: https://github.com/daixianceng/formik-material-fields
Установка:
npm install --save formik-material-fields
Использование:
import React, { Component } from 'react';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
import { FormikTextField } from 'formik-material-fields';
const validationSchema = Yup.object().shape({
username: Yup.string().required(),
});
const initialValues = {
username: '',
};
class MyForm extends Component {
render() {
return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={this.props.onSubmit}
>
{({ isValid }) => (
<Form autoComplete="off">
<FormikTextField
name="username"
label="Username"
margin="normal"
fullWidth
/>
</Form>
)}
</Formik>
);
}
}
Ответ 4
Вы также можете попробовать эту библиотеку, которая выполняет тяжелую работу за вас и реализует код оболочки вокруг компонентов Material-UI (включая <TextField />
): https://github.com/stackworx/formik-material-ui.
Установка:
yarn add formik-material-ui
В своем компоненте формы Formik передайте компонент <TextField />
в качестве пропеллера компонента компонента Formik <Field />
.
import { Formik, Field, Form } from 'formik';
import { TextField } from 'formik-material-ui';
<Field
name="email"
label="Email"
type="email"
component={TextField}
/>
Formik продолжит обрабатывать проверку должным образом и отобразит компонент Material UI и сообщение об ошибке. В документации есть дополнительные детали для других компонентов ввода Mui и для помощи в настройке.