In this article we are going to learn about formik. A form library in React. We will learn how to build forms with formik in react with different examples and in a step by step manner
Step1 : Formik: Installation and setup
Open your react application or if you are just starting our create a new react application with create-react-app or with Next.js like
npx create-react-app
npx create-next-app
Next, open your terminal and install the dependencies
npm install formik yup reactstrap bootstrap
Yup is a validation library and reactStrap is a css framework for beautification (bootstrap for react)
Now that we have installed the dependencies, let us open the App.js file and import our dependencies
If you are looking for a React Native Chat SDK, you can consider DeadSimpleChat React Native SDK
before creating a form let us create a validation schema using YUP. If you are not interested in validation simply skip this step
const validationSchema = Yup.object().shape({
username: Yup.string().required('Username is required'),
email: Yup.string().email('Invalid email format').required('Email is required'),
password: Yup.string().min(6, 'Password must be at least 6 characters').required('Password is required'),
});
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.
Step 2 Set the initial values for the form
Let us set the initial values for the form
You can set initial values by defining an Object
const initialValues = {
username: '',
email: '',
password: '',
};
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.
Step 3: Create a structure for the form and a Formik component
Lets us wrap the DOM elements in a formik component and pass teh validation schema and the initial values for the form
function App() {
return (
<Container>
<h1>Example of a Formi FOrm</h1>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({ isSubmitting }) => (
<Form>
{/*add the form elements here*/}
</Form>
)}
</Formik>
</Container>
);
}
Step 4: Add form fields and submit button
Add the form fields and the submit button to the form that we created above like so
<FormGroup>
<Label for="username">Username:</Label>
<Field type="text" name="username" id="username" className="form-control" />
<ErrorMessage name="username" component="div" className="text-danger" />
</FormGroup>
<FormGroup>
<Label for="email">Email:</Label>
<Field type="email" name="email" id="email" className="form-control" />
<ErrorMessage name="email" component="div" className="text-danger" />
</FormGroup>
<FormGroup>
<Label for="password">Password:</Label>
<Field type="password" name="password" id="password" className="form-control" />
<ErrorMessage name="password" component="div" className="text-danger" />
</FormGroup>
<Button type="submit" color="primary" disabled={isSubmitting}>
{isSubmitting ?'Submitting...' : 'Submit'}
</Button>
Step 5: Adding the OnSubmit functionality
In this step let us add the onSubmit functionality
onSubmit={(values, { setSubmitting }) => { setTimeout(() => { alert(JSON.stringify(values, null, 2)); setSubmitting(false); }, 400); }}
Step 6 Styling the form
We can style our form to look good using the bootstrap library that we imported earlier. This is complementary and not related to formik
.container {
max-width: 600px;
margin: 50px auto;
}
.form-group {
margin-bottom: 15px;
}
Step 7: Running the app
Now that we have built the formik application let us run it.
Open your terminal and write the below code:
npm start
What is formik?
Formik is a react library for creating forms. It is small and easy to work with. Formik consists of React Hooks and components that solves these three problems related to form
- Storing and retriving values from state
- error messaging and form validation
- handling form submission
Formik makes testing, refactoring and maintaining the forms very easy by colocation all the above functionality in one place
Simple Formik Examples
Let us consider a simple example of a newsletter form sign up. We will be building a newsletter sign up for a blog with just one field that is email.
We can write this with a few lines of code and formik
We pass our initialValues and a submission function to the useForm hook. The hook returns form state and helper methods in a var called formik
These are the helper methods that are returned and are important
- handleSubmit: submission handler
- handleChange: change handler to pass to each of
<input>
<select>
and<textarea>
values
: forms current values
We can pass each of these to their respective props. We now have a working form powered by formik
Instead of managing everything related to forms and writing our own custom event hanlers we can just useFormik()
This is neat but with just one input it is unclear what benefits the formik offers. Let us consider an example with 3 inputs. An input for user's first name another for user's last name and the last one for a user's email
Let us study the code further
- We can use the same changeHandler function for each HTML input that is the
handleChange
- The property that we defined in the
initialValues
have the same id and name as the HTML attribute for each input - We can accesse the fields value like (email - > formail.values.email)
Validation
Next let us add validation to our forms that would tell the users that there is something missing in the form or that they have made some mistake while filling out the form
If you want to use the browsers in-built validation just add the required in the element like
<input required />
or specify min and max lengths, or add a regex pattern to control user behaviour
There are som eproblems with the built in HTML validation that the formik wants to solve these are
- HTML validation doesn't work in react native
- Its hard to show custom error messages in the built in HTML form
Formik keeps track of a form's values and validation as well as error messages. To validate with formik create a function for validation and pass validate
function to the useFormik() hook
If the error is there the custom validation function should produce and error object matching the initialValues
import React from 'react';
import { useFormik } from 'formik';
// the custom validation object must return a object with key value pairs
//with matching shape (similar) to the values/initialValues
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
} else if (values.firstName.length > 15) {
errors.firstName = 'Must be 15 characters or less';
}
if (!values.lastName) {
errors.lastName = 'Required';
} else if (values.lastName.length > 20) {
errors.lastName = 'Must be 20 characters or less';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address';
}
return errors;
};
const SignupForm = () => {
//initial form values should be passed to the useFormik() hook.
// A validate function will be called when form values change and submit
//funtion will be called when the form is submitted
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
validate,
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
value={formik.values.firstName}
/>
{formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
value={formik.values.lastName}
/>
{formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
value={formik.values.email}
/>
{formik.errors.email ? <div>{formik.errors.email}</div> : null}
<button type="submit">Submit</button>
</form>
);
};
formik.errors is populated by the custom validation function
By default Formik validates after each keystroke, input fields blur event and prior to submission when the submit button is pressed
The onSubmit function is called when the validation is passed by the formik
Visited fields
Next we need to implement visited fields as the formik is throwing errors all over the place when the form first loads
to implement the visited fields, we will need the formik's touched object. The formik stores the data on touched Object and also mirrors the shape of values / initialValues
The key /value pairs of touched are field names and boolean true or false
To use the touched property we pass the formik.handleBlur to each input onBlur prop
import React from 'react';
import { useFormik } from 'formik';
const validate = values => {
const errors = {};
if (!values.firstName) {
errors.firstName = 'Required';
} else if (values.firstName.length > 20) {
errors.firstName = 'less than 20 char';
}
if (!values.lastName) {
errors.lastName = 'Required';
} else if (values.lastName.length > 20) {
errors.lastName = 'less than 20 char';
}
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 're type the email address';
}
return errors;
};
const SignupForm = () => {
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
},
validate,
onSubmit: values => {
alert(JSON.stringify(values, null, 2));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
name="firstName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.firstName}
/>
{formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
name="lastName"
type="text"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.lastName}
/>
{formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
{formik.errors.email ? <div>{formik.errors.email}</div> : null}
<button type="submit">Submit</button>
</form>
);
};
Conclusion
In this article we wrote about the formik form validation and how you can use it in your website or react native application
formik makes building forms an easy task. It is also a very small library and doesn't bloat your application
It comes with Yup schema validation and other beautiful features
Thank you for reading