web-dev-qa-db-ja.com

FormikとMaterial-UI

Material-UIテキストフィールドでFormikを使用しようとしています。そのようです:

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コンポーネントを書きたくありません。

12
Adam Marczyk

コメントで言及したように、FormikまたはReactFinalFormのこのサンプルで行ったように、実際には「ラッパー」コンポーネントを実装することをお勧めします。

考え方は同じです。カスタム「ラッパー」コンポーネントを実装して、Material-UIコンポーネントをラップし、FormikまたはReactFinalForm APIの小道具をマップします。

このアプローチの利点は、2つのフレームワーク間のマッピングを1か所に集中させることです。これにより、毎回マッピングを繰り返す必要がなくなります。

12
Ricovitch

別のライブラリが必要なわけではなく、独自のラッパーを作成する必要もないと思います。コードを少し調整する必要があると思います。

ある問題の1つは、onChange関数をMaterial TextFieldに渡さないため、firstNameのフォーム値が常にnullであるため、名前を入力した場合でも常にエラーが発生することです。 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)
        }
    />
    )}
/>
10
needsleep

これを試すことができます: 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>
    );
  }
}
5
Cosmo Dai

また、このライブラリを試すこともできます。このライブラリは、あなたのために重労働を行い、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は引き続き検証を処理し、マテリアルUIコンポーネントとエラーメッセージをレンダリングします。ドキュメントには、他のMui入力コンポーネントに関する追加の詳細があり、カスタマイズを支援します。

0
whitehall