ReactForm
Home/Tools/Checkbox

React Form with Checkbox

Checkbox groups store their state as an array of selected values, which requires a different state pattern than simple text inputs. The toggle logic — add if not present, remove if already there — is a one-liner with filter and spread. A "Select all" feature makes the component immediately useful for real-world forms like skill selectors or preferences.

ReactForm Team·May 2026·3 min read

The challenge

Handling checkbox groups and syncing state can become messy in React forms, especially when implementing select-all and toggle logic.

  • Toggling a checkbox in an array state without mutating the original array
  • Implementing "Select all" and "Deselect all" without duplicating state logic
  • Syncing the "Select all" checkbox indeterminate state when only some options are checked
  • Knowing which items are selected when submitting the form alongside other field types

Working code example

Here is a complete, self-contained working example you can drop directly into any React project. It uses Tailwind CSS for styling and requires no external dependencies beyond React itself.

CheckboxGroup.jsx
import { useState } from 'react';

const SKILLS = ['React', 'TypeScript', 'Node.js', 'CSS', 'Testing'];

export default function CheckboxGroup() {
  const [selected, setSelected] = useState([]);
  const [submitted, setSubmitted] = useState(false);

  const toggle = (skill) => {
    setSelected((prev) =>
      prev.includes(skill) ? prev.filter((s) => s !== skill) : [...prev, skill]
    );
  };

  const selectAll = () => setSelected([...SKILLS]);
  const clearAll = () => setSelected([]);
  const allSelected = selected.length === SKILLS.length;

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!selected.length) { alert('Please select at least one skill'); return; }
    setSubmitted(true);
  };

  if (submitted)
    return (
      <div className="p-6 bg-green-50 rounded-2xl text-green-700">
        <p className="font-semibold">Skills submitted!</p>
        <p className="text-sm mt-1">{selected.join(', ')}</p>
      </div>
    );

  return (
    <form onSubmit={handleSubmit} className="max-w-sm mx-auto p-6 bg-white rounded-2xl shadow space-y-4">
      <h2 className="text-xl font-bold text-gray-800">Your Skills</h2>
      <div className="flex gap-3">
        <button type="button" onClick={allSelected ? clearAll : selectAll}
          className="text-xs px-3 py-1 rounded-full border border-teal-600 text-teal-600 hover:bg-teal-50 transition">
          {allSelected ? 'Deselect all' : 'Select all'}
        </button>
        <span className="text-xs text-gray-400 self-center">{selected.length} / {SKILLS.length} selected</span>
      </div>
      <div className="space-y-2">
        {SKILLS.map((skill) => (
          <label key={skill} className="flex items-center gap-3 cursor-pointer group">
            <input
              type="checkbox"
              checked={selected.includes(skill)}
              onChange={() => toggle(skill)}
              className="w-4 h-4 accent-teal-600 rounded"
            />
            <span className={`text-sm ${selected.includes(skill) ? 'text-teal-700 font-medium' : 'text-gray-700'}`}>
              {skill}
            </span>
          </label>
        ))}
      </div>
      <button type="submit"
        className="w-full bg-teal-600 text-white font-semibold py-2 rounded-lg hover:bg-teal-700 transition">
        Save Skills
      </button>
    </form>
  );
}

How ReactForm.co helps

ReactForm's visual builder handles all of the above — checkbox configuration, validation rules, state management, and responsive layout — without writing a single line of code. Drag fields onto the canvas, configure their properties in the sidebar, and get production-ready React output. You can publish the form and collect responses instantly, or export the JSX to drop into your own codebase.

Build this form visually

Frequently asked questions

How do I store checkbox group state in React?

Use an array of selected values in useState. When a checkbox is toggled, add the value if it is not already in the array, or remove it if it is: setSelected(prev => prev.includes(val) ? prev.filter(v => v !== val) : [...prev, val]). This pattern avoids mutating state and works for any number of options.

How do I make a "Select all" checkbox with an indeterminate state?

Track the indeterminate state in a useEffect and set it directly on the DOM element via a ref: checkboxRef.current.indeterminate = selected.length > 0 && selected.length < options.length. React does not support the indeterminate attribute declaratively, so you need to use a ref for this.

What is the difference between a checkbox group and a single checkbox?

A single checkbox stores a boolean in state. A checkbox group stores an array of selected values. For a single checkbox, use onChange={e => setBool(e.target.checked)}. For a group, use the toggle pattern with an array. Always use type="checkbox" and read e.target.checked, not e.target.value.

Related topics

Build this form visually — no code needed

ReactForm.co handles checkbox fields, validation, conditional logic, and responsive layout automatically. Publish in minutes and collect responses for free.