React Conf 2024 - Key Announcements and Takeaways
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 :
- FormikWrapper
- FormikController
- 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,
- Input
- TextArea
- Select
- RadioButtons
- 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 to choose from, this has to be considered when creating our Select component and rest are same as above. option
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