开发者问题收集

Formik 和 Material-UI

2018-08-31
48256

我正在尝试将 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 负责外观。 我想将 errors.firstName 传递给 TextField 组件,但错误无法正确显示。我该如何修复它,以便仍然清晰易读?我不想编写自己的 TextField 组件。

3个回答

我认为您不需要另一个库,甚至不需要创建自己的包装器,我认为您需要稍微调整一下代码。

您遇到的一个问题是,您没有在 Material TextField 中传递 onChange 函数,因此 firstName 的表单值始终为空,因此您总是会收到错误,即使您输入了名称。 尝试在您的 TextField 上添加名称或 ID 以及 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)
        }
    />
    )}
/>
needsleep
2018-09-02

正如评论中提到的,实现“包装器”组件可能实际上是一个好主意,就像他们在 Formik 或 ReactFinalForm 的示例中所做的那样:

想法是一样的:实现自定义“包装器”组件来包装 Material-UI 组件并映射 Formik 或 ReactFinalForm API 属性。

这种方法的优点是集中在一个地方两个框架之间的映射,这样您就不必每次都重复映射,并且如果其中一个框架引入了重大更改,您只需更改那些自定义的“包装器”组件即可。

Ricovitch
2018-09-07

你可以试试这个: https://github.com/daixianeng/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>
    );
  }
}
Cosmo Dai
2018-12-12