福米克和 Material-UI

Formik and 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 负责外观。 我想将 errors.firstName 传递给 TextField 组件,但错误显示不正确。我怎样才能修复它,让它仍然清晰可读?我不想编写自己的 TextField 组件。

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

您遇到的一个问题是您没有在 Material TextField 中传递 onChange 函数,因此 firstName 的表单值始终为 null,因此您总是会收到错误消息,即使您输入了姓名。 尝试在您的 TextField 和 onChange 函数上添加名称或 ID,如下所示:

<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)
        }
    />
    )}
/>

如评论中所述,实现 "wrapper" 组件实际上可能是个好主意,就像他们在 Formik 或 ReactFinalForm 的示例中所做的那样:

想法是一样的:实现自定义 "wrapper" 组件来包装 Material-UI 组件并映射 Formik 或 ReactFinalForm APIs 道具。

这种方法的优点是将两个框架之间的映射集中在一个地方,这样你就不用每次都重复映射,如果其中一个框架引入了破坏性的变化,你只需要改变那些自定义的"wrapper" 个组件。

你可以试试这个: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>
    );
  }
}

您也可以试试这个库,它会为您完成繁重的工作并围绕 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 输入组件的文档中还有其他详细信息,可帮助进行自定义。

在此处查看 <Field /> 的 formik 文档:https://jaredpalmer.com/formik/docs/api/field

例如,您可以使用 Material 的 OutlinedInput 来设置您的输入样式:

<Field as={OutlinedInput} />

如果您需要将更多道具传递给 OutlinedInput,只需将它们添加到 Field,它就会将它们传递给 OutlinedInput:

<Field as={OutlinedInput} color="primary" InputProps={{ startAdornment: <InputAdornment position="start"><AccountCircle /></InputAdornment> }} />

要使用 material-uiformik,您可以使用 官方 formik 文档https://formik.org/docs/examples/with-material-ui

您可以使用 setFieldValue 方法 对于创建自定义输入更改处理程序很有用

<Formik
  initialValues={{
    name: "",
  }}
  onSubmit={(values: any) => console.log(values)}
>
  {({  handleSubmit, setFieldValue }) => (
    <Form noValidate autoComplete="off" onSubmit={handleSubmit}>
      <TextField
        onChange={(event) => setFieldValue("name", event.target.value)} 
        type="text"
        label="Name"
      />
    </Form>
  )}
</Formik>