ReactForm
Home/Tools/Select Dropdown

React Form with Select Dropdown

A select dropdown becomes significantly more complex when one dropdown's options depend on another's selection — a common pattern for category and subcategory pickers, country and city pairs, or department and team selectors. The key is resetting the dependent field's value whenever the parent changes so you never submit a subcategory that no longer belongs to the selected category.

ReactForm Team·May 2026·4 min read

The challenge

Select fields often involve mapping options and handling default values manually, and dependent dropdowns add another layer of complexity.

  • Resetting the dependent dropdown value when the parent selection changes
  • Defining the option data structure cleanly so adding new categories does not touch render logic
  • Setting a meaningful default placeholder option without submitting an empty string
  • Styling native select elements consistently across browsers — this requires custom wrappers

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.

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

const CATEGORIES = {
  frontend: { label: 'Frontend', subs: ['React', 'Vue', 'Angular', 'Svelte'] },
  backend: { label: 'Backend', subs: ['Node.js', 'Python', 'Ruby', 'Go'] },
  mobile: { label: 'Mobile', subs: ['React Native', 'Flutter', 'Swift', 'Kotlin'] },
  devops: { label: 'DevOps', subs: ['Docker', 'Kubernetes', 'AWS', 'Terraform'] },
};

export default function CategoryDropdown() {
  const [category, setCategory] = useState('');
  const [subCategory, setSubCategory] = useState('');
  const [submitted, setSubmitted] = useState(false);

  const handleCategory = (e) => {
    setCategory(e.target.value);
    setSubCategory('');
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!category || !subCategory) { alert('Please select both a category and a technology'); return; }
    setSubmitted(true);
  };

  if (submitted)
    return (
      <div className="max-w-sm mx-auto p-6 bg-green-50 rounded-2xl text-green-700">
        <p className="font-semibold">Selection saved!</p>
        <p className="text-sm mt-1">{CATEGORIES[category].label}{subCategory}</p>
      </div>
    );

  const subs = category ? CATEGORIES[category].subs : [];

  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">Technology Selector</h2>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">Category</label>
        <select
          value={category}
          onChange={handleCategory}
          className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-teal-500 bg-white">
          <option value="">Select a category…</option>
          {Object.entries(CATEGORIES).map(([key, { label }]) => (
            <option key={key} value={key}>{label}</option>
          ))}
        </select>
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">Technology</label>
        <select
          value={subCategory}
          onChange={(e) => setSubCategory(e.target.value)}
          disabled={!category}
          className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-teal-500 bg-white disabled:opacity-50 disabled:cursor-not-allowed">
          <option value="">{category ? 'Select a technology…' : 'Select a category first'}</option>
          {subs.map((s) => <option key={s} value={s}>{s}</option>)}
        </select>
      </div>
      <button type="submit"
        className="w-full bg-teal-600 text-white font-semibold py-2 rounded-lg hover:bg-teal-700 transition">
        Save Selection
      </button>
    </form>
  );
}

How ReactForm.co helps

ReactForm's visual builder handles all of the above — select dropdown 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 build a dependent (cascading) dropdown in React?

Store the parent selection in state and derive the child options from it. When the parent changes, reset the child value to an empty string: setChild(""). This prevents a stale child value from being submitted. Define your data as an object keyed by parent values so the child options are easy to look up.

How do I set a default placeholder in a select element?

Add an <option value="">Select an option…</option> as the first child and control it with value={state} in the select element. If you want to prevent users from selecting the placeholder, you can add a disabled attribute to that option. Always check that the value is not an empty string before submitting.

Can I style a native select element with Tailwind CSS?

Only partially. You can style the outer box, border, padding, and text color. The dropdown itself — the open state and each option — is rendered natively by the OS and cannot be styled with CSS. For fully custom dropdowns, use a library like Headless UI or Radix UI Select, or build one from a div and an options list.

Related topics

Build this form visually — no code needed

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