Elevate Your React Projects: Reusable Custom Hooks for Form Validation

Oladipupo Ishola
5 min readSep 2, 2024

--

React Hooks Image

As we continue to build applications, we have to think not only about the code working but also about development principles, application scalability robustness, and code maintenance. I sometimes wrote an article about form validation in React using Formik and Yup last year. See the link below for the article.

This short article updates the previous article with a simple solution that can be further customized. Sometimes when I write an article, the intention of the article is always for me to serve as a second brain for a quick lookup when needed and possibly be of help to someone by providing a solution to a problem and also to reduce the endless Google search, been there, trust me. However, this turns out to be the opposite. It was someone trying to use the article and reach out to me trying to create a custom hook and his implementation was not working as intended and reaching out for help.

Sharing this is not to communicate pride or a form of showoff but to show that this, my good friend, opened my eyes to the part I was not thinking about, and this is me saying thank you. After working together to find a solution, this got me thinking about the need for the custom hook.

It dawned on me that the approach in the previous article works better when only validating one or two forms in a small application but imagine in larger applications with multiple forms to be validated, practically one has to import formik components everywhere they are needed, and doing so, the code has to be repeated across multiple places in the codebase as a result, which violates the DRY programming principle and can also be reused in other projects, viola I see the reason why my good friend needs a custom hook.

The custom hook

Since we are using React or its related frameworks, to solve the issue of code repetition, we make use of React Hook. React hooks allow the creation of custom hooks to reuse some stateful logic or behaviors between components and not the state itself, custom hooks let us do this without adding more components to the tree. In case you’re new to Hooks, here is an article on Hooks in a Glance and Why React Hooks. You can also check my articles on some of the most used custom hooks that you can start using asap in your projects, from basics to advanced.

As I mentioned from the start it will be a simple reusable hook, the hook will take an initial value of a generic that extends the FormikValues since we are trying to make the hook work with different types of form values, validation schema of yup ObjectSchema of generic type as with the initial value and the onSubmit function that takes the form values to submit the data to the backend.

Then saved the returned values of useFormik hook taking the initial values, validationSchema, and the onSubmit function into the formik variable, and then returned the formik object.

import { useFormik, FormikValues } from "formik";
import { ObjectSchema } from "yup";

type Submit = (values: FormikValues) => void;

function useForm<T extends FormikValues>(
initialValues: T,
validation: ObjectSchema<T>,
onSubmit: Submit
) {
const formik = useFormik({
initialValues,
validationSchema: validation,
onSubmit
});
return { formik };
}
export { useForm };

Let’s use the hook by calling the useForm hook inside the form component, declaring the initialValues, the validationSchema, and the onSubmit function, passing them as arguments to the useForm hook, and registering the form components with the returned formik object as below.


import React, { useState, useEffect } from "react";
import { useForm } from "../hooks/useForm";
import { FormikValues } from "formik";
import "../form/Form.css";
import { validationSchema } from "../utils/schema";

function MyForm() {
const [status, setStatus] = useState<boolean>(false);
const initialValues = {
name: "",
email: "",
};

const onSubmit = (values: FormikValues) => {
// mock submit
setTimeout(() => {
console.log("Form submitted with values:", values);
setStatus(true);
}, 1000);
};

const { formik } = useForm(initialValues, validationSchema, onSubmit);
const {
handleSubmit,
handleChange,
handleBlur,
values,
errors,
touched,
isSubmitting,
handleReset,
} = formik;

useEffect(() => {
if (status) {
handleReset(values);
setStatus(false);
}
}, [status, handleReset, values]);

return (
<main className="main">
<form onSubmit={handleSubmit}>
<label htmlFor="name">
Name:
<input
type="text"
id="name"
name="name"
value={values.name}
onChange={handleChange}
onBlur={handleBlur}
className={errors.name && "input-err"}
/>
{touched.name && errors.name && (
<div className="error">{errors.name}</div>
)}
</label>
<label htmlFor="email">
Email:
<input
type="email"
id="email"
name="email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={errors.name && "input-err"}
/>
{touched.email && errors.email && (
<div className="error">{errors.email}</div>
)}
</label>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting" : "Submit"}
</button>
</form>
</main>
);
}

export default MyForm;

There you have it, we have managed to solve the issue with repeating code by the use of React Custom hooks, the hook can be used across the entire codebase making the code more clean and DRY and the good thing is, you can further customize and reuse the hook in every of your other projects.

Thank you for reading.

The demo’s GitHub repository is available here, where you can view the entire code as well as the CSS stylings.

Happy coding!

And if you haven’t already subscribed to me, you can just click here to Subscribe to my newsletter ❤️ and Be the first to read my newly published articles.

And finally, if you’d like to support my writing journey, you can help me keep going by buying me a coffee.
Buy a coffee

👇 Do you know you can Clap 50 times 🙃 . Let us see how much you Clap for me. It matters to me.❤️ 👇

--

--

Oladipupo Ishola

Tech Writer | Full Stack Developer | Frontend Developer | Backend Developer | Co-Building @techverseacademy | Mentor & Code Instructor | MLH ’21 Alum