少なくとも1つのフォームを含まないWebアプリを作成することはめったにありません。 多くの場合、アプリ全体は単なる一連のフォームです。 これらの各フォームには、状態管理、イベントハンドラー、および多くの場合、ある種のクライアント側のデータ検証が必要です。 Formik は、これらすべてを小さなパッケージで実行することを目的としており、彼らが主張するように、「涙を流さずに」実行します。

入門

formikの使用を開始するには、npmまたはyarnを介してプロジェクトに追加する必要があります。

$ npm install --save formik
# or
$ yarn add formik

依存関係を追加したら、それを使用するプロジェクトに必ずインポートしてください。 この記事では、FormikFormヘルパーコンポーネントの両方を使用します。

import { Formik, Form } from "formik";

Formコンポーネントは、Formikコンポーネントに接続されたonSubmitハンドラーを自動的に接続する、標準のform要素のラッパーであり、時間をさらに節約します。

Formikコンポーネント

Formikの本当の魔法は、Formikコンポーネントで発生します。 このコンポーネントは、フォームをラップするために使用され、レンダープロップを介して状態値とハンドラーを公開します。

このコンポーネントは、プロパティを取得してデフォルト値を設定し、送信された値を検証し、送信を処理できます。

Formikコンポーネントが、後で作成する基本的なログインフォームを検索する方法は次のとおりです。

<Formik
  // Sets up our default values
  initialValues={{ email: "", password: "" }}

  // Validates our data
  validate={values => {
    const errors = {};

    if (!values.email) errors.email = "Required";

    if (
      !/^[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
    ) {
      errors.email = "You must supply a valid email address";
    }

    if (values.password.length < 8) {
      errors.password = "Passwords must be at least 8 characters";
    }

    if (values.email === values.password) {
      errors.password =
        "Your password shouldn't be the same as your email";
    }

    return errors;
  }}

  // Handles our submission
  onSubmit={(values, { setSubmitting }) => {
    // This is where you could wire up axios or superagent
    console.log("Submitted Values:", values);
    // Simulates the delay of a real request
    setTimeout(() => setSubmitting(false), 3 * 1000);
  }}
>
  {props => (
    <div>This is where your Form and form elements will go!</div>
  )}
</Formik>

yupjoiなどのオブジェクトスキーマバリデーターに精通している場合は、validateプロパティをスキップしてvalidationSchemaを渡すことができます。代わりは。

フォームコンポーネント

前述のように、Formコンポーネントは、onSubmitハンドラーなどを自動的に接続するform要素のドロップイン置換です。

通常どおりにフォームの入力をラップするために使用します。

<Formik>
  {props => (
    <Form>
      <label>My Input</label>
      <input type="text" />
    </Form>
  )}
</Formik>

入力の状態

すぐに使用できるFormikのrenderプロパティは、イベントハンドラーを公開して、フォーム入力への変更(「タッチ」されているかどうか、値、エラーなど)を管理します。

フォーム全体については、フォームが検証中か送信中か、およびフォームを簡単にリセットできるイベントハンドラーを確認できます。

props.valuesおよびprops.errorsは、フォームフィールドに対応するプロパティを持つオブジェクトです。

props.handleChangeおよびprops.handleBluronChangeおよびonBlurプロパティに渡して、変更と入力が「タッチ」されたかどうかを追跡できます。

この「タッチされた」値は、ページの読み込み時ではなく、ユーザーが要素を操作した後にのみエラーを表示したい場合に便利です(これはIMHOが推奨されます)。

props.dirtyは、ユーザーがフォームを変更するとtrueに設定されます。

状態値props.isValidatingおよびprops.isSubmittingは、ユーザーがプロセスのどの段階にあるかを示します。 ローダーを表示したり、フォームや個々のボタンを無効にしたりするのに最適です。

すべてをまとめる

正式にFormikedされた後の、電子メールとパスワードを使用した単純なログインフォームは次のようになります。

<Formik
  // Sets up our default values
  initialValues={{ email: "", password: "" }}

  // Validates our data
  validate={values => {
    const errors = {};

    if (!values.email) errors.email = "Required";

    if (
      !/^[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
    ) {
      errors.email = "You must supply a valid email address";
    }

    if (values.password.length < 8) {
      errors.password = "Passwords must be at least 8 characters";
    }

    if (values.email === values.password) {
      errors.password =
        "Your password shouldn't be the same as your email";
    }

    return errors;
  }}

  // Handles our submission
  onSubmit={(values, { setSubmitting }) => {
    // This is where you could wire up axios or superagent
    console.log("Submitted Values:", values);
    // Simulates the delay of a real request
    setTimeout(() => setSubmitting(false), 3 * 1000);
  }}
>
  {props => (
    <Form>
      <label htmlFor="email">Email</label>
      <div>
        <input
          name="email"
          type="email"
          placeholder="Enter your account email"
          value={props.values.email}
          onChange={props.handleChange}
          onBlur={props.handleBlur}
          style={{
            borderColor:
              props.errors.email && props.touched.email && "red"
          }}
        />
        {props.errors.email && props.touched.email && (
          <div style={{ color: "red" }}>{props.errors.email}</div>
        )}
      </div>
      <label htmlFor="password">Password</label>
      <div>
        <input
          name="password"
          type="password"
          placeholder="Enter your account password"
          value={props.values.password}
          onChange={props.handleChange}
          onBlur={props.handleBlur}
          style={{
            borderColor:
              props.errors.password && props.touched.password && "red"
          }}
        />
        {props.errors.password && props.touched.password && (
          <div style={{ color: "red" }}>{props.errors.password}</div>
        )}
      </div>
      <input
        type="submit"
        value="Submit"
        disabled={props.isSubmitting}
      />
      &nbsp;
      <input
        type="reset"
        value="Reset"
        onClick={props.handleReset}
        disabled={!props.dirty || props.isSubmitting}
      />
    </Form>
  )}
</Formik>

結論

Formikは、フォームを作成するための使い慣れたレンダリングプロップベースのアプローチを提供します。

通常作成する冗長なボイラープレートとステートメント管理ロジックのほとんどは、フォームでかなり複雑な状態管理を実行するのに十分な電力を内部で提供しながら、適切に処理されます。

この記事のコードを試してみたい場合は、CodeSandboxで確認できます。

乾杯!