DEV Community

Cover image for Simple way to write forms in React with Formik
Hamid
Hamid

Posted on

Simple way to write forms in React with Formik

Formik is a best library and I use it every time. So today I am writing this post for fundamentals of formik and it covers the use of formik in simple way .

Create and style a login form

I created login form like this

 <form className="form">
        <div className="field">
          <label htmlFor="email">Email Address</label>
          <input
            id="email"
            name="email"
            type="email"
            placeholder="email"
          />
        </div>
        <div className="field">

          <input
            id="password"
            name="password"
            type="password"
            placeholder="password"
          />
        </div>
        <button type="submit" className="submit-btn">
          Login
        </button>
      </form>
Enter fullscreen mode Exit fullscreen mode

and styled it like this

.App {
  font-family: sans-serif;
  text-align: center;
  display: grid;
  place-items: center;
}
.form {
  width: 300px;
  display: grid;
  gap: 10px 0px;
  margin-top: 50px;
  background-color: #ddd;
  border-radius: 8px;
  padding: 10px;
}
.field {
  display: flex;
  justify-content: space-between;
  padding-bottom: 10px;
}
.submit-btn {
  width: 80px;
}
.error {
  color: red;
  font-size: 12px;
  justify-self: start;
  font-style: italic;
  padding-bottom: 10px;
  line-height: 3px;
}

Enter fullscreen mode Exit fullscreen mode

After this, you'll get a login form same as this

image

Initialize formik default states

Lets import the useFormik first from the formik.

import { useFormik } from "formik";
Enter fullscreen mode Exit fullscreen mode

Now you can initialize the initialValues of form using useFormik hook .

const formik = useFormik({
    initialValues: {
      email: "",
      password: ""
    },
)}
Enter fullscreen mode Exit fullscreen mode

let's apply formik to our input fields .

   ...
          <input
            id="email"
            name="email"
            type="email"
            placeholder="email"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.email}
          />
     ...
          <input
            id="password"
            name="password"
            type="password"
            placeholder="password"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.password}
          />
Enter fullscreen mode Exit fullscreen mode

Apply validations on login fields

I used Yup library to apply validations on my fields
So first import Yup like this .

import * as Yup from "yup";
Enter fullscreen mode Exit fullscreen mode

Then I added validationSchema for my login fields

const validationSchema = yup.object({
    email: yup
      .string()
      .email('Please enter a valid email address')
      .required('Email is required'),
    password: yup
      .string()
      .min(8, 'Please enter strong password')
      .required('Password is required'),
  })
  const formik = useFormik({
    initialValues: {
      email: "",
      password: ""
    },
    validationSchema,
)};
Enter fullscreen mode Exit fullscreen mode

Here Yup is validating if the values of the field are provided; if yes, then is it correct format or not.
So if any error happens according to our validation schema, it will be stored in formik's errors object and we can print it beside or below the field like this .

{formik.touched.email && formik.errors.email ? (
         <span className="error">{formik.errors.email}</span>
) : null}
Enter fullscreen mode Exit fullscreen mode

Now our form looks like this with validation errors

image

Write submit form function

The last step is to create submit function and perform your operation on formik values. You can navigate to the next screen, call API, or anything you want to do. I just set a state on submit and shown a message to a user on the login .

const formik = useFormik({
    initialValues: {
      email: "",
      password: ""
    },
    validationSchema,
    onSubmit: (values) => {
      setIsLoggedIn(true);
    }
  });
Enter fullscreen mode Exit fullscreen mode

and pass formik handleSubmit function to your form like this

<form className="form" onSubmit={formik.handleSubmit}>
Enter fullscreen mode Exit fullscreen mode

and here your form is ready with field validations!!
You can find the full source code here

https://codesandbox.io/s/unruffled-tharp-uti1k?file=/src/App.js:727-781

Discussion (12)

Collapse
lukeshiru profile image
LUKESHIRU

You can use the native HTML5 validations instead, making your code way simpler:

import { useState } from "react";

export const App = () => {
  const [loggedIn, setLoggedIn] = useState(false);
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  return loggedIn ? (
    <h1>You're logged in!</h1>
  ) : (
    <form
      onSubmit={() => {
        // You can use `email` and `password` with the API
        setLoggedIn(true);
      }}
    >
      <label htmlFor="email">Email</label>
      <input
        id="email"
        name="email"
        onChange={event => setEmail(event.currentTarget.value)}
        placeholder="Email"
        required
        type="email"
        value={email}
      />
      <label htmlFor="password">Password</label>
      <input
        id="password"
        minLength="8"
        name="password"
        onChange={event => setPassword(event.currentTarget.value)}
        placeholder="Password"
        required
        type="password"
        value={password}
      />
      <button type="submit">Login</button>
    </form>
  );
};
Enter fullscreen mode Exit fullscreen mode

Formik might make some partial sense with extremely complex forms, but for login/signup forms, a few states and the native validations are more than enough.

Cheers!

Collapse
victorocna profile image
Victor Ocnarescu

I respectfully disagree. How about touched fields handling? Or error messages and states? Submit count for your forms? Even validation that is not your basic HTML5 validation? These are all handled by Formik by default and you don't have to worry about them.

My forms have become really clean after I started using this library. I cannot recommend Formik enough.

Collapse
lukeshiru profile image
LUKESHIRU

It's ok if you use Formik for complex scenarios if you don't forget about the basic HTML5 validations and input types. More often than not, folks forget to use the email type for emails, or tel for phones, and so on. This makes a11y and mobile UX better. The same applies to basic validations which with Formik only will work if JS is loaded, and will not work otherwise (SSR without hydration), while the native validations will work either way.
So even if you use Formik, you'll have to deal with the HTML5 input validations and types, at that point, for simple forms like a login, you're adding complexity with Formik instead of simplifying it.

Thread Thread
victorocna profile image
Victor Ocnarescu

The drawback to using "basic" form logic instead of a specific package like Formik is it can get complicated along the way. And most of the times it does get more complicated.

Imagine you start a simple login form, everything is great. Basic HTML5 validation works. Then your client comes up and wants to display an error message tied to the username field, only when the form was already submitted and the username does not exist (check the login on Netflix for this exact scenario).

Now here is the part it gets messy. You don't exactly know what to do. Should you implement these yourself? Or maybe a package like Formik? It did not get too complicated, it's still a form with 2 fields: username and password.

Of course, you are right about the HTML5 validation. You can get that for free in every browser and it improves UX. But Formik (or a similar package that improves forms) is the next best thing. Forms get messier and messier as your projects evolve.

Thread Thread
hamid2117 profile image
Hamid Author

Yes you get a point .

Collapse
hamid2117 profile image
Hamid Author

Yes you are right bro .Just I want to cover fundamentals of formik and yup .My goal not for login it's for fundamentals ....

Collapse
victorocna profile image
Victor Ocnarescu • Edited on

Formik is indeed awesome. Have you ever tried Formik Fields? They automatically bind onChange, onBlur and value to your input (and you don't have to declare them all the time).

Without Formik Fields:

<input
  id="password"
  name="password"
  type="password"
  placeholder="password"
  onChange={formik.handleChange}
  onBlur={formik.handleBlur}
  value={formik.values.password}
/>
Enter fullscreen mode Exit fullscreen mode

With Formik Fields:

<Field
  id="password"
  name="password"
  type="password"
  as="input"
/>
Enter fullscreen mode Exit fullscreen mode
Collapse
hamid2117 profile image
Hamid Author

Incredible I will give it try sir .

Collapse
hyggedev profile image
Chris Hansen

Thanks for this guide! Detailed yet very quick, much appreciated. 💯

Collapse
hamid2117 profile image
Hamid Author

It's my pleasure 😊.

Collapse
b0nec0de profile image
Anton Bondarev

Thanks for the article! I especially like its brevity. Personally I hate making forms by the way )

Collapse
hamid2117 profile image
Hamid Author

It's my pleasure Sir 😊.