Reusable Form Components - AntStack
Jul 23, 2021 5 min read

Reusable Form Components using React + Formik + Yup

Introduction

This Blog helps to build a simple form with basic elements like input, textarea, radio, select, and checkbox using formik that manage form data, submission, and validation .

What is Formik and Why Formik Form?

Formik is a small group of React components and hooks for building forms in React and React Native.

Formik Forms not only helps in managing form data, form submission, form validation, and displaying error messages but also helps you to deal with forms in a scalable, performant, easy way and one more important thing is, it supports advanced validation with Yup.

What is Yup?

Yup is a JavaScript schema builder for value parsing and validation. Define a schema, transform a value to match, validate the shape of an existing value, or both. Yup schema is extremely expressive and allows modelling complex, interdependent validations, or value transformations.

Prerequisites

  • HTML
  • CSS
  • Javascript + ES6
  • React

Installation

npm install --save formik yup

Lets Build

We shall have 3 Components :

  1. FormikWrapper
  2. FormikController
  3. FormElement

FormikWrapper.js

We use this component as a simple reusable formik wrapper.

import React from "react"
import { Formik, Form } from "formik"
import * as Yup from "yup"
import FormikController from "FormikController.js"

function FormikWrapper() {
  const choices = [
    { key: "choice a", value: "choicea" },
    { key: "choice b", value: "choiceb" },
  ]

  const initialValues = {
    email: "",
    description: "",
    selectChoice: "",
    radioChoice: "",
    checkBoxChoice: "",
  }
  const validationSchema = Yup.object({
    email: Yup.string().required("Required"),
    description: Yup.string().required("Required"),
    selectChoice: Yup.string().required("Required"),
    radioChoice: Yup.string().required("Required"),
    checkBoxChoice: Yup.array().required("Required"),
  })
  const onSubmit = values => console.log("Form data", values)
  return (
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={onSubmit}
    >
      {formik => (
        <Form>
          <FormikController
            control="input"
            type="email"
            label="Email"
            name="email"
          />
          <FormikController
            control="textarea"
            label="Description"
            name="description"
          />
          <FormikController
            control="select"
            label="Select your choice"
            name="selectChoice"
            option={choices}
          />
          <FormikController
            control="radio"
            label="Click your choice"
            name="radioChoice"
            option={choices}
          />
          <FormikController
            control="checkbox"
            label="select your choices"
            name="checkBoxChoice"
            option={choices}
          />
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  )
}
export default FormikContainer

FormikController.js

This component is capable of rendering different types of form elements based on particular prop.

import React from "react"
import Input from "Input.js"
import TextArea from "TextArea.js"
import Select from "Select.js"
import RadioButtons from "RadioButton.js"
import CheckBoxes from "CheckBoxes.js"

function FormikController(props) {
  const { control, ...rest } = props
  switch (control) {
    case "input":
      return <Input {...rest} />
    case "textArea":
      return <TextArea {...rest} />
    case "select":
      return <Select {...rest} />
    case "radio":
      return <RadioButtons {...rest} />
    case "checkbox":
      return <CheckBoxes {...rest} />
    default:
      return null
  }
}
export default FormikController

FormElement.js

This component is the core form element which includes,

  1. Input
  2. TextArea
  3. Select
  4. RadioButtons
  5. Checkboxes

Component for Input Element

In this Input Formik control component, there are 3 distinct elements <label/> an HTML element, <Field/> a Formik Component, <ErrorMessage/> an error message component from formik.

import React from "react"
import { Field, ErrorMessage } from "formik"

function Input(props) {
  const { name, label, ...rest } = props
  return (
    <div>
      <label htmlFor={name}> {label}</label>
      <Field name={name} {...rest} />
      <ErrorMessage name={name} />
    </div>
  )
}
export default Input

Component for TextArea Element

Here also there are 3 main elements , <label/> an HTML element,<ErrorMessage/> an error message component from formik and <Field/> a Formik Component which inturn render textarea HTML element.

import React from "react"
import { Field, ErrorMessage } from "formik"

function Textarea(props) {
  const { label, name, ...rest } = props
  return (
    <div>
      <label htmlFor={name}>{label}</label>
      <Field as="textarea" id={name} name={name} {...rest} />
      <ErrorMessage name={name} />
    </div>
  )
}
export default TextArea

Component for Select Element

Here <Field/> a Formik Component which inturn renders select HTML element, Onclick of the field renders a dropdown with list of option to choose from, this has to be considered when creating our Select component and rest are same as above.

import React from "react"
import { Field, ErrorMessage } from "formik"

function Select(props) {
  const { label, name, options, ...rest } = props
  return (
    <div>
      <label htmlFor={name}>{label}</label>
      <Field as="select" id={name} name={name} {...rest}>
        {options.map(option => {
          return (
            <option key={option.value} value={option.value}>
              {option.key}
            </option>
          )
        })}
      </Field>
      <ErrorMessage name={name} />
    </div>
  )
}

export default Select

Component for RadioButtons Element

<Field/> is a list of input and label elements that allows you to make one selection, this has to be considered when creating a radio button component.

import React from "react"
import { Field, ErrorMessage } from "formik"

function RadioButtons(props) {
  const { label, name, options, ...rest } = props
  return (
    <div>
      <label>{label}</label>
      <Field name={name}>
        {formik => {
          const { field } = formik
          return options.map(option => {
            return (
              <div key={option.key}>
                <input
                  type="radio"
                  id={option.value}
                  {...field}
                  {...rest}
                  value={option.value}
                  checked={field.value === option.value}
                />
                <label htmlFor={option.value}>{option.key}</label>
              </div>
            )
          })
        }}
      </Field>
      <ErrorMessage name={name} />
    </div>
  )
}

export default RadioButtons

Component for CheckBoxes Element

Here also <Field/> is a list of input and label elements that allows you to make one or more selections.

import React from "react"
import { Field, ErrorMessage } from "formik"

function Checkboxes(props) {
  const { label, name, options, ...rest } = props
  return (
    <div>
      <label>{label}</label>
      <Field name={name}>
        {formik => {
          const { field } = formik
          return options.map(option => {
            return (
              <div key={option.key}>
                <input
                  type="checkbox"
                  id={option.value}
                  {...field}
                  {...rest}
                  value={option.value}
                  checked={field.value.includes(option.value)}
                />
                <label>{option.key}</label>
              </div>
            )
          })
        }}
      </Field>
      <ErrorMessage name={name} />
    </div>
  )
}

export default Checkboxes

Conclusion

We can extend it to a custom React Hook that returns Formik states and helpers. It is used internally to create the component and is also a high performant.

References

Explore limitless possibilities with AntStack's frontend development capabilities. Empowering your business to achieve your most audacious goals. Build better. Build with us.

Author(s)

Topics

Share this blog

Your Digital Journey deserves a great story.

Build one with us.

Blog Recommendation

6 min read

May 30, 2023

react-native.png

6 min read

Jan 10, 2023

Jan 10, 2023

6 min read

Jan 10, 2023

header 3.png

5 min read

Mar 21, 2022

Mar 21, 2022

5 min read

Mar 21, 2022

React-Performance-Optimization.png

6 min read

Jan 10, 2022

Jan 10, 2022

6 min read

Jan 10, 2022

18 min read

Nov 18, 2021

7 min read

Oct 22, 2021

7 min read

Oct 14, 2021

5 min read

Jul 23, 2021

5 min read

May 10, 2021

11 min read

Apr 21, 2021

cookie

These cookies are used to collect information about how you interact with this website and allow us to remember you. We use this information in order to improve and customize your browsing experience and for analytics and metrics about our visitors on this website.

If you decline, your information won’t be tracked when you visit this website. A single cookie will be used in your browser to remember your preference not to be tracked.

Build With Us