Categories
React

Make Form Handling Easy in React Apps with Formik — Checkboxes and Radio Buttons

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik.

Checkboxes

We can bind checkbox values to states with Formik.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        toggle: false,
        checked: []
      }}
      onSubmit={(values) => {
        alert(JSON.stringify(values, null, 2));
      }}
    >
      {({ values }) => (
        <Form>
          <label>
            <Field type="checkbox" name="toggle" />
            {`${values.toggle}`}
          </label>
          <div>Checked</div>
          <div>
            <label>
              <Field type="checkbox" name="checked" value="apple" />
              apple
            </label>
            <label>
              <Field type="checkbox" name="checked" value="orange" />
              orange
            </label>
            <label>
              <Field type="checkbox" name="checked" value="grape" />
              grape
            </label>
          </div>

          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We set the initialValues to what we want.

In the first Field component, we set name to 'toggle' to bind to the toggle field.

This will bind the checked value to the values.toggle property.

It’ll be true when it’s checked and false otherwise.

In the div, we have 3 Field components.

We set the value in addition to the name to let us populate the checked array with the value prop value of the checkboxes that are checked.

When we submit the form, we see the checked items in checked and toggle is either true or false depending on whether it’s checked or not.

Radio Buttons

Formik also makes binding states to radio buttons easy.

To do this, we write:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        picked: ""
      }}
      onSubmit={(values) => {
        alert(JSON.stringify(values, null, 2));
      }}
    >
      {({ values }) => (
        <Form>
          <div>Picked</div>
          <div>
            <label>
              <Field type="radio" name="picked" value="apple" />
              One
            </label>
            <label>
              <Field type="radio" name="picked" value="orange" />
              Two
            </label>
            <div>Picked: {values.picked}</div>
          </div>

          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We set the name of the radio button groups to the same name.

And we also set the value for each.

Then we can pick one radio from the ones with the same name value.

And we’ll see the value with the value.picked property.

Conclusion

We can bind checkbox and radio button values to states with Formik.

Categories
React

Make Form Handling Easy in React Apps with Formik — Error Messages and Binding to Arrays and Nested Properties

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik.

Displaying Error Messages

We can display form validation error messages by rendering the values of the errors object.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";

const schema = Yup.object().shape({
  email: Yup.string().email("Invalid email").required("Required")
});

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        email: ""
      }}
      validationSchema={schema}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ errors, touched }) => (
        <Form>
          <Field name="email" />
          {touched.email && errors.email && <div>{errors.email}</div>}
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

Then we render the errors.email property to get the value of the email field.

When we type in something that’s not an email address, we’ll see the error message displayed.

Arrays and Nested Objects

Formik works with arrays and nested objects.

For example, we can bind form fields to nested properties by writing:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        social: {
          facebook: "",
          twitter: ""
        }
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="social.facebook" />
        <Field name="social.twitter" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

In the initialValues prop, we have the social object with some properties inside.

To bind to those, we just set the name prop of the Field components to the property paths of those properties.

Then values in the onSubmit callback would have those values set.

We can also bind our Field input values to array entries.

To do this, we write:

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        friends: ["james", "mary"]
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="friends[0]" />
        <Field name="friends[1]" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We just set the name prop to the path to the array entry we want to bind to.

Also, we can remove nesting by adding properties with dots to separate the path segments.

For instance, we can write;

import React from "react";
import { Formik, Form, Field } from "formik";

export const FormExample = () => (
  <div>
    <Formik
      initialValues={{
        "owner.name": ""
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="['owner.name']" />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  </div>
);
export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We have the 'owner.name' property in initialValues .

Then we set the name prop to ['owner.name'] to do the binding automatically.

Conclusion

We can display form validation error messages and bind input fields to nested properties and array entries with Formik.

Categories
React

Make Form Handling Easy in React Apps with Formik— Field Level Validation

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik.

Field Level Validation

We can add field-level validation by creating validation functions and passing it into the validate prop of the Field component.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";

function validateEmail(value) {
  let error;
  if (!value) {
    error = "Required";
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i.test(value)) {
    error = "Invalid email address";
  }
  return error;
}

export const FormExample = () => (
  <div>
    <h1>Signup</h1>
    <Formik
      initialValues={{
        email: ""
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ errors, touched, isValidating }) => (
        <Form>
          <Field name="email" validate={validateEmail} />
          {errors.email && touched.email && <div>{errors.email}</div>}
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);

export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We create the validateEmail function that takes the value parameter, which has the input value.

Then we check the value and return validation error messages after we checked if the value is valid.

In FormExample , we create the form with the Formik and Form components.

initialValues has the initial value of each field.

The Field component has the name prop set to the same value as in the initialValues .

validate has the validation function we created earlier.

errors has the error message.

touched has the touched state of the input.

isValidating tells us whether the form is being validated.

Manually Triggering Validation

We can manually trigger validation with Formik.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";
function validateUsername(value) {
  let error;
  if (value === "admin") {
    error = "Nice try!";
  }
  return error;
}

export const FormExample = () => (
  <div>
    <h1>Signup</h1>
    <Formik
      initialValues={{
        username: "",
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ errors, touched, validateField, validateForm }) => (
        <Form>
          <Field name="username" validate={validateUsername} />
          {errors.username && touched.username && <div>{errors.username}</div>}
          <button type="button" onClick={() => validateField("username")}>
            Check Username
          </button>
          <button
            type="button"
            onClick={async () => {
              const result = await validateForm();
              console.log(result);
            }}
          >
            Validate All
          </button>
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);

export default function App() {
  return (
    <div className="App">
      <FormExample />
    </div>
  );
}

We have the validateUsername function that validates the username field.

In the Form element, we have the Check Username button that calls validateField with 'username' , which is the name value of the Field component.

The names will be matched so validateUsername function will be run.

We can validate all the fields in the form with the validateForm function, which returns a promise with any errors that are found.

So if we type in ‘admin’ into the input, the returned promise will resolve to:

{username: "Nice try!"}

Conclusion

We can add field level validation and manually trigger form validation with Formik.

Categories
React

Make Form Handling Easy in React Apps with Formik and Yup — withFormik and Yup

Formik is a library that makes form handling in React apps easy.

Yup is a library that integrates with Formik.

In this article, we’ll look at how to handle form inputs with Formik.

Validation

One way to add validation with Formik is to transform our form component into a form with validation with the withFormik higher-order component.

For instance, we can write:

import React from "react";
import { withFormik } from "formik";

const MyForm = (props) => {
  const {
    values,
    touched,
    errors,
    handleChange,
    handleBlur,
    handleSubmit
  } = props;
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        onChange={handleChange}
        onBlur={handleBlur}
        value={values.email}
        name="email"
      />
      {errors.email && touched.email && <div id="feedback">{errors.email}</div>}
      <button type="submit">Submit</button>
    </form>
  );
};

const MyEnhancedForm = withFormik({
  mapPropsToValues: () => ({ email: "" }),
  validate: (values) => {
    const errors = {};
    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;
  },

  handleSubmit: (values, { setSubmitting }) => {
    setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      setSubmitting(false);
    }, 1000);
  },

  displayName: "BasicForm"
})(MyForm);

export default function App() {
  return (
    <div className="App">
      <MyEnhancedForm />
    </div>
  );
}

to do that.

We create the MyForm component to get the properties we need from the props .

values has the inputted values.

touched has the touched state of each input.

errors has the form validation errors we set in the validate method/

handleChange has the form change handler.

handleBlur has the blur handler.

handleSubmit has the submit handler.

Next, we create the MyEnhancedForm compoennt which has the validation.

mapPropsToValues is set to a function that returns the initial values.

validate returns an error object after checking the values from the values parameter.

handleSubmit has the form submit function.

values has the form values.

setSubmitting has a function to set the submit state of the form.

displayName sets the displayName property of the component for debugging.

Then we use MyEnhancedForm in App to render the form.

Basic Validation with Yup

To make form validation easier, we can use the Yup library to add validation to our form.

For instance, we can write:

import React from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";

const SignupSchema = Yup.object().shape({
  email: Yup.string().email("Invalid email").required("Required")
});

export const ExampleForm = () => (
  <div>
    <h1>Signup</h1>
    <Formik
      initialValues={{
        email: ""
      }}
      validationSchema={SignupSchema}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ errors, touched }) => (
        <Form>
          <Field name="email" type="email" />
          {errors.email && touched.email ? <div>{errors.email}</div> : null}
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);

export default function App() {
  return (
    <div className="App">
      <ExampleForm />
    </div>
  );
}

We create the SignupSchema with the Yup.object() method.

We pass in an object into the shape method to add validation to the object.

To validate strings, we call Yup.string().email() method.

The argument of 'email' has the validation error message.

required makes the field required.

Then we just pass the returned object into the validationSchema prop.

onSubmit has the submit handler.

initialValues has the initial values.

Then to create the Field object, we set the name to the property, we have in thew shape method’s argument to apply the form validation.

touched has the touched state of the input.

Conclusion

We can add form validation with Formik, and we can make this easier with Yup.

Categories
React

Make Form Handling Easy in React Apps with Formik

Formik is a library that makes form handling in React apps easy.

In this article, we’ll look at how to handle form inputs with Formik.

Installation

We can install Formik by running:

npm install formik --save

or

yarn add formik

Basic Usage

We can use it by writing:

import React from "react";
import { Formik } from "formik";

export default function App() {
  return (
    <div className="App">
      <Formik
        initialValues={{ email: "", password: "" }}
        validate={(values) => {
          const errors = {};
          if (!values.email) {
            errors.email = "Required";
          } else if (
            !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$/i.test(values.email)
          ) {
            errors.email = "Invalid email address";
          }
          return errors;
        }}
        onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 400);
        }}
      >
        {({
          values,
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit,
          isSubmitting
        }) => (
          <form onSubmit={handleSubmit}>
            <input
              type="email"
              name="email"
              onChange={handleChange}
              onBlur={handleBlur}
              value={values.email}
            />
            {errors.email && touched.email && errors.email}
            <input
              type="password"
              name="password"
              onChange={handleChange}
              onBlur={handleBlur}
              value={values.password}
            />
            {errors.password && touched.password && errors.password}
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
          </form>
        )}
      </Formik>
    </div>
  );
}

initialValues has the initial values.

validate is a function that lets us validate form values entered.

values has the values that we entered.

We set the errors object with the errors for the fields.

onSubmit has a function that has the entered values in the values object.

setSubmitting is a function that can we can run to set the form submit state.

In the form element, we set the onSubmit form to the handleSubmit function from the parameter of the render prop to run onSubmit if it’s value.

values.email and values.password have the form value for each field.

handleChange lets us incorporate the entered values into the values object in various places.

onBlur has the handleBlur method to handle blur events.

touched has the touched state for each form field.

isSubmitting has the submitting state of the form.

We can simplify the code with the Form , Field , and ErrorMessage components.

For instance, we can reduce the code above to:

import React from "react";
import { ErrorMessage, Field, Form, Formik } from "formik";

export default function App() {
  return (
    <div className="App">
      <Formik
        initialValues={{ email: "", password: "" }}
        validate={(values) => {
          const errors = {};
          if (!values.email) {
            errors.email = "Required";
          } else if (
            !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$/i.test(values.email)
          ) {
            errors.email = "Invalid email address";
          }
          return errors;
        }}
        onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 400);
        }}
      >
        {({ isSubmitting }) => (
          <Form>
            <Field type="email" name="email" />
            <ErrorMessage name="email" component="div" />
            <Field type="password" name="password" />
            <ErrorMessage name="password" component="div" />
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
          </Form>
        )}
      </Formik>
    </div>
  );
}

The components replace the form input elements and error text.

As long as the name values match between the Field and ErrorMessage , we’ll see the same values displayed.

Conclusion

We can handle forms in React easily with Formik.