Formik Components.
Tags: formik, components, reusable, react
Published: 2021-10-29 14:29:28

- [Formik Components](#formik-components)
  - [Login Form With Formik Components](#login-form-with-formik-components)
  - [Formik Reusable Components](#formik-reusable-components)

## Formik Components

Formik provides a few Components to be used that will save us more time, reduce code duplication, and make the code more consistent and organized.

### Login Form With Formik Components

- Import `Formik`, `Form`, `Field` and `ErrorMessage` from `formik`.
- Wrap and return the entire form inside `<Formik>` Component with `formik` as a parameter.
- Add `initialValues`, `onSubmit` and `validationSchema` as **Props** to `<Formik>` Component.
- Replace the native `<form>` element with the `<Form>` Component.
- Wrap and return the `label`, `input`, and the `validation div message` inside `<Field>` with `formikField` as a parameter.
- Add the `name` attribute to the `<Field>` component instead of the `<input>` element.
- spread `{...formikField.field}` inside the `<input>` element.
- Wrap and return the `validation div` inside `<ErrorMessage>` component with `ErrMessage` as a parameter and add the `name` attribute to it.
- log `formikField` inside a `<pre>` to see the entire `formikField` object.

```jsx
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as yup from "yup";

/**
 * LoginFormikComponents Component
 */
const LoginFormikComponents = () => {
  const initialValues = {
    email: "",
    password: "",
    rememberMe: false,
  };
  const onSubmit = (values) => console.log(JSON.stringify(values, null, 4));
  const validationSchema = yup.object({
    email: yup
      .string()
      .email("Please enter a valid email address")
      .required("Email field is required"),
    password: yup.string().required("Password field is required"),
  });

  return (
    <Formik
      initialValues={initialValues}
      onSubmit={onSubmit}
      validationSchema={validationSchema}
    >
      {(formik) => {
        return (
          <Form>
            <div style={{ padding: 20 }}>
              <Field name="email">
                {(formikField) => {
                  return (
                    <>
                      <label htmlFor="email" style={{ display: "block" }}>
                        email
                      </label>
                      <input type="email" id="email" {...formikField.field} />
                      <ErrorMessage name="email">
                        {(errMessage) => {
                          return (
                            <div style={{ color: "red" }}>{errMessage}</div>
                          );
                        }}
                      </ErrorMessage>
                      <pre>{JSON.stringify(formikField, null, 4)}</pre>
                    </>
                  );
                }}
              </Field>

              <Field name="password">
                {(formikField) => {
                  return (
                    <>
                      <label htmlFor="password" style={{ display: "block" }}>
                        password
                      </label>
                      <input
                        type="password"
                        id="password"
                        {...formikField.field}
                      />
                      <ErrorMessage name="password">
                        {(errMessage) => {
                          return (
                            <div style={{ color: "red" }}>{errMessage}</div>
                          );
                        }}
                      </ErrorMessage>
                      <pre>{JSON.stringify(formikField, null, 4)}</pre>
                    </>
                  );
                }}
              </Field>

              <Field name="rememberMe">
                {(formikField) => {
                  return (
                    <>
                      <label htmlFor="rememberMe" style={{ display: "block" }}>
                        remember me
                      </label>
                      <input
                        type="checkbox"
                        id="rememberMe"
                        defaultChecked={formikField.field.value}
                        {...formikField.field}
                      />
                      <pre>{JSON.stringify(formikField, null, 4)}</pre>
                    </>
                  );
                }}
              </Field>
              <button style={{ display: "block" }}>submit</button>
            </div>
            <pre>{JSON.stringify(formik, null, 4)}</pre>
          </Form>
        );
      }}
    </Formik>
  );
};
export default LoginFormikComponents;
```

## Formik Reusable Components

As we can see inside each `<Field>` component there are

- `<label>`
- `<input>`
- `<ErrorMessage>`

So, it's a good chance to create a Reusable Component that includes all of that.

FormikErrorMessage.jsx

```jsx
import React from "react";
import { ErrorMessage } from "formik";

/**
 * FormikErrorMessage Component
 */
const FormikErrorMessage = ({ name }) => {
  return (
    <ErrorMessage name={name}>
      {(errMessage) => {
        return <div style={{ color: "red" }}>{errMessage}</div>;
      }}
    </ErrorMessage>
  );
};

export default FormikErrorMessage;
```

FormikField.jsx

```jsx
import React from "react";
import { Field } from "formik";
import FormikErrorMessage from "./FormikErrorMessage";

/**
 * FormikField Component
 */
const FormikField = ({ name, type, label }) => {
  return (
    <Field name={name}>
      {(formikField) => {
        return (
          <>
            <label htmlFor={name} style={{ display: "block" }}>
              {label}
            </label>
            <input
              type={type}
              id={name}
              {...formikField.field}
              defaultChecked={formikField.field.value}
            />
            <FormikErrorMessage name={name} />
            <pre>{JSON.stringify(formikField, null, 4)}</pre>
          </>
        );
      }}
    </Field>
  );
};

export default FormikField;
```

And here is the final code after using the reusable components.

LoginFormikComponentsShared.jsx

```jsx
import React from "react";
import { Formik, Form } from "formik";
import * as yup from "yup";
import FormikField from "./shared/FormikField";

/**
 * LoginFormikComponents Component
 */
const LoginFormikComponents = () => {
  const initialValues = {
    email: "",
    password: "",
    rememberMe: false,
  };
  const onSubmit = (values) => console.log(JSON.stringify(values, null, 4));
  const validationSchema = yup.object({
    email: yup
      .string()
      .email("Please enter a valid email address")
      .required("Email field is required"),
    password: yup.string().required("Password field is required"),
  });

  return (
    <Formik
      initialValues={initialValues}
      onSubmit={onSubmit}
      validationSchema={validationSchema}
    >
      {(formik) => {
        return (
          <Form>
            <div style={{ padding: 20 }}>
              <FormikField label="Email" name="email" type="email" />
              <FormikField label="Password" name="password" type="password" />
              <FormikField
                label="Remember Me"
                name="rememberMe"
                type="checkbox"
              />
              <button style={{ display: "block" }}>submit</button>
            </div>
            <pre>{JSON.stringify(formik, null, 4)}</pre>
          </Form>
        );
      }}
    </Formik>
  );
};
export default LoginFormikComponents;

```

<a href="https://www.linkedin.com/in/youssefzidan/" target="_blank">
    <img src="https://img.shields.io/badge/LinkedIn-%230077B5.svg?&style=flat-square&logo=linkedin&logoColor=white" alt="LinkedIn">