TutorialsCourses
Course Menu
Formik for Beginners

Checkbox Field

Intro

Despite checkbox fields being an input once type="checkbox" is added there are slight changes that make them annoying to deal with. For example rather than value informing the browser of the value it swaps to checked being true or false.

We'll take a look at both ways to use a checkbox, with Field and the useField hook.

Basic Field

The most basic method is rendering Field as before, but passing in the type="checkbox". Here you will get just a normal input field. It's as simple as you'll get with Formik and checkboxes but you'll have limited control.

<Field name="acceptTerms" className="mr-2 leading-tight" type="checkbox" />

Field Checkboxes

The Field variety like we learned is rendered by passing Component to the field which we pass our MySpecialField component. One thing that is new is that we need to pass type="checkbox" to the Field component itself.

This tells the internals for Formik that it doesn't need to supply just a value prop like you would with a text field. It also needs to supply a checked prop so that the input field will toggle.

<Field name="acceptTerms" type="checkbox" component={MySpecialField} />

Now you will still receive almost the same field as before except now there will be one extra property on it which is checked: true. So not only will you get the name, the value, but checked which is how checkboxes are controlled.

{
  "name": "acceptTerms",
  "value": false,
  "checked": false
}

One caveat is you will still need to supply type="checkbox" to the input. That doesn't flow through on the field.

const MySpecialField = ({ field }) => {
  return (
    <label className="text-gray-500 font-bold">
      <input {...field} className="mr-2 leading-tight" type="checkbox" />
      <span className="text-sm">Accept Terms</span>
    </label>
  );
};

useField Checkboxes

Finally the other form is using the useField hook. The useField hook can take both a string name as the only property, or when you need to enable Formik to understand checkboxes pass in an object with name and the type set to checkbox.

Spread the field on like normal, apply type="checkbox" and you're checkbox input is all wired up.

const MySpecialFieldHook = () => {
  const [field] = useField({ name: "acceptTerms", type: "checkbox" });
  return (
    <label className="text-gray-500 font-bold">
      <input {...field} className="mr-2 leading-tight" type="checkbox" />
      <span className="text-sm">Accept Terms</span>
    </label>
  );
};

One Caveat

One caveat to note is that Formik will coerce whatever the value is to be true or false, but also maintain the value.

So for example if the value for acceptedTerms was totesAccept. That would still be what appears on the values, and checked would be true. In order to get checked not to appear as true we would need to set our acceptedTerms value to be something falsy like null, false, undefined, or 0.

<Formik
  initialValues={{
    acceptTerms: "totesAccept",
  }}
/>

Doing anything but true and false will break Formik unless you're handling all of stuff manually. It is best practice to just use true and false for your values and nothing else.

Ending

Putting it all together we have 3 checkboxes all driven off of the same value, but rendered multiple ways.

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

const MySpecialField = ({ field }) => {
  return (
    <label className="text-gray-500 font-bold">
      <input {...field} className="mr-2 leading-tight" type="checkbox" />
      <span className="text-sm">Accept Terms</span>
    </label>
  );
};

const MySpecialFieldHook = () => {
  const [field] = useField({ name: "acceptTerms", type: "checkbox" });
  return (
    <label className="text-gray-500 font-bold">
      <input {...field} className="mr-2 leading-tight" type="checkbox" />
      <span className="text-sm">Accept Terms</span>
    </label>
  );
};

function App() {
  const handleSubmit = (values) => {
    console.log(values);
  };

  return (
    <div className="App">
      <Formik
        initialValues={{
          acceptTerms: false,
        }}
        onSubmit={handleSubmit}
      >
        {() => {
          return (
            <Form className="h-screen flex content-center flex-col justify-center">
              <div className="space-x-4 flex content-center justify-center">
                <label className="text-gray-500 font-bold">
                  <Field
                    name="acceptTerms"
                    className="mr-2 leading-tight"
                    type="checkbox"
                  />
                  <span className="text-sm">Accept Terms</span>
                </label>
                <Field
                  name="acceptTerms"
                  type="checkbox"
                  component={MySpecialField}
                />
                <MySpecialFieldHook />

                <button
                  type="submit"
                  className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
                >
                  Submit
                </button>
              </div>
            </Form>
          );
        }}
      </Formik>
    </div>
  );
}

export default App;