typescript Formik 和 Material-UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52111447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:37:42  来源:igfitidea点击:

Formik and Material-UI

javascriptreactjstypescriptmaterial-uiformik

提问by n3stle

I am trying to use Formik with Material-UI text field. Like so:

我正在尝试将 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;

I want Formik to be responsible for validation and Material-UI for looks. I want to pass errors.firstName to TextField component but the error doesn't display correctly. How can I fix it so it still will be clear to read? I don't want to write my own TextField component.

我希望 Formik 负责外观的验证和 Material-UI。我想将 errors.firstName 传递给 TextField 组件,但错误无法正确显示。我该如何修复它才能让它仍然清晰可读?我不想编写自己的 TextField 组件。

回答by needsleep

I don't think you need another library or even create your own wrapper, I think you need to tweek your code a bit.

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

One problem you have is that you don't pass an onChange function in the Material TextField so the form value of firstName is always null and so you always get the error, even if you have entered a name. Try adding a name or id on your TextField and an onChange function like so:

您遇到的一个问题是您没有在 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)
        }
    />
    )}
/>

回答by Ricovitch

As mentionned in comments, it may actually be a good idea to implement "wrapper" components, like they did in this samples from Formik or ReactFinalForm :

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

The idea is the same : implement custom "wrapper" components to wrap Material-UI components and map Formik or ReactFinalForm APIs props.

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

The advantages of this approach is to centralize in one place the mapping between the two frameworks, so that you do not repeat the mapping each time, and if one of the framework introduces breaking changes you just have to change those custom "wrapper" components.

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

回答by Cosmo Dai

You can try this: https://github.com/daixianceng/formik-material-fields

你可以试试这个:https: //github.com/daixianceng/formik-material-fields

Installation:

安装:

npm install --save formik-material-fields

Usage:

用法:

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

回答by whitehall

You could also try this library, which does the heavy-lifting for you and implements the wrapper code around Material-UI components (including <TextField />): https://github.com/stackworx/formik-material-ui.

你也可以试试这个库,它为你做了繁重的工作,并围绕 Material-UI 组件(包括<TextField />)实现了包装器代码:https: //github.com/stackworx/formik-material-ui

Installation:

安装:

yarn add formik-material-ui

In your Formik form component, pass the <TextField />component as the component prop of the Formik <Field />component.

在您的 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 will continue to handle the validation as expected and will render the Material UI component and error message. There are additional details in the docs for other Mui input components and to aid with customization.

Formik 将继续按预期处理验证,并将呈现 Material UI 组件和错误消息。其他 Mui 输入组件的文档中还有其他详细信息,以帮助进行自定义。

回答by ben

Check out the formik docs for <Field />here: https://jaredpalmer.com/formik/docs/api/field

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

As an example you could use Material's OutlinedInput to style your input:

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

<Field as={OutlinedInput} />