DEV Community

Cover image for Formik Components.
Youssef Zidan
Youssef Zidan

Posted on • Edited on

9

Formik 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.
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;
Enter fullscreen mode Exit fullscreen mode

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

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;
Enter fullscreen mode Exit fullscreen mode

FormikField.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;
Enter fullscreen mode Exit fullscreen mode

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

LoginFormikComponentsShared.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;

Enter fullscreen mode Exit fullscreen mode


LinkedIn

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay