How to Build Dependent Dropdowns in React

In many web applications, we often encounter forms where selecting an option in one dropdown unlocks a new set of options in another. These interconnected dropdowns, commonly known as dependent or cascading dropdowns, play a crucial role in creating ...

Jan 30, 2025 - 22:55
 0
How to Build Dependent Dropdowns in React

In many web applications, we often encounter forms where selecting an option in one dropdown unlocks a new set of options in another. These interconnected dropdowns, commonly known as dependent or cascading dropdowns, play a crucial role in creating a seamless and intuitive form-filling experience.

Whether it's selecting a country to reveal corresponding states or choosing a product category to display specific items, these dropdowns simplify complex choices for everyone. For developers, implementing dependent dropdowns is a practical challenge that combines logic, usability, and dynamic data handling.

In this tutorial, you’ll learn how to implement this type of dropdown in your React application.

Table of Contents

What is a Dependent Dropdown?

A dependent dropdown is a UI element in which the available options in one dropdown are determined by the selection made in another dropdown. For example, consider a scenario where you have two dropdowns:

  1. Country Dropdown: The user selects a country.

  2. City Dropdown: Based on the selected country, the list of available cities in the second dropdown will be filtered accordingly.

This kind of interaction is crucial for forms that require complex, context-sensitive data inputs.

How Does a Dependent Dropdown Work?

Dependent dropdowns work by having the second dropdown’s options dynamically updated based on the value selected in the first dropdown. This dynamic change is typically achieved by:

  1. Listening to user input: When the user selects an option in the first dropdown, an event (usually onChange) triggers a function to update the state.

  2. Fetching new data: This updated state can be used to either filter the existing data or make an API call to fetch the new list of options.

  3. Rendering new data: The second dropdown is then updated with the new options, providing the user with relevant choices.

Steps to Create Dependent Dropdowns in React

Step 1: Set up Your React Project

If you’re new to React and wish to follow along, check out the Vite docs and follow the steps to create your React project. When you’re done, come back here and let’s continue building.

If you already have a React project you want to use, that’s great too.

Step 2: Structure the Component

For simplicity, let’s assume we are building a two-level dependent dropdown where the first dropdown lets you choose a country, and the second dropdown displays cities based on the selected country.

Also, in the country dropdown, we’ll have another option for entering a country name that is not included in the countries options. The user can then proceed to enter their country in a text input.

First, create a new file named DependentDropdown.js or DependentDropdown.jsx. Inside this file, define a functional component called DependentDropdown.

Now we’ll be going through the following steps to build our dependent dropdown:

Declare Variables for Storing Data

We need to create static data for the values of our countries and cities:

  // Static country data
  const countries = [
    { id: 1, name: 'USA' },
    { id: 2, name: 'Canada' },
    { id: 3, name: 'Other' },
  ];

  // Static city data corresponding to countries
  const cities = {
    USA: ['New York', 'Los Angeles', 'Chicago'],
    Canada: ['Toronto', 'Vancouver', 'Montreal'],
  };
  • countries is an array of objects. Each object having properties of id and name.

  • cities is an object with country names as keys and the values as array of cities.

Declare State Variables

For each selection of either country or cities, we want to be able to keep track of the values selected. We also want to be able to populate the cities option after a country selection has been made. To do that, we need to declare some states.

If the concept of state is new to you, you can read my article on state here.

  const [selectedCountry, setSelectedCountry] = useState('');
  const [availableCities, setAvailableCities] = useState([]);
  const [selectedCity, setSelectedCity] = useState('');
  const [otherCountry, setOtherCountry] = useState('');
  • The selectedCountry state is declared and its initial value is set to an empty string.

  • The availableCities state is declared and its initial value is set to an empty array.

  • The selectedCity state is declared and its initial value is set to an empty string.

  • The otherCountry state is declared and its initial value is set to an empty string.

Handling Events

In the process of making a selection in the dropdown, we want some actions to be performed. Event handlers enable us to do that in the case of an event, which in this case is the onChange event.

  const handleCountryChange = (e) => {
    const country = e.target.value;
    setSelectedCountry(country);
    setAvailableCities(cities[country] || []);
    setSelectedCity(''); 
     if (country !== 'Other') {
      setOtherCountry('');
    }
  };

Here’s what’s going on in the handleCountryChange function:

  • Grabs the value of the selected option in the dropdown (the country that was selected).

  • The setSelectedCountry updates the state variable (selectedCountry) with the newly selected country.

  • cities[country] looks up the list of cities for the selected country from the cities object.

    • If cities[country] is found, it sets that list of cities as the available cities.

    • If no cities are found for the selected country (cities[country] is undefined), the || [] ensures that an empty array ([]) is used as a fallback, preventing errors when trying to display the cities.

  • When the user changes the country selection, the setSelectedCity function resets the selectedCity to an empty string.

  • If the country selected is not ‘Other’, the otherCountry state is reset to an empty string. This ensures that if the user had previously typed something into the "Other" input, that text is cleared once they select a different country (for example, "USA" or "Canada").

For the ‘Other’ country selection, we just need to keep track of the value entered into the input. The setOtherCountry function updates the value entered. And this is how it is done:

  const handleOtherCountryChange = (e) => {
    setOtherCountry(e.target.value);
  };

For the cities change, we don’t need to do much because the selected country determines which cities are displayed. All we need to do is to update the selectedCity to the value of the selected option in the dropdown, which is the city that is selected.

In React, the updater function does the updating of state variables, so the setSelectedCity handles this in this case.

The handleCityChange function will be:

  const handleCityChange = (e) => {
    setSelectedCity(e.target.value);
  };

Returning JSX

The DependentDropdown component renders three main elements: the Country dropdown, the City dropdown, and the Country text input.

A dropdown in HTML is a combination of the element, we’ll give it a value attribute of selectedCountry and also attach the handleCountryChange function to it.

     
      <select id="country" value={selectedCountry} onChange={handleCountryChange}>
        <option value="">Select a countryoption>
        {countries.map((country) => (
          <option key={country.id} value={country.name}>
            {country.name}
          option>
        ))}
      select>

Also,

  • Inside the , we map over the countries array and dynamically create an for each country object in the array.

  • Each country’s name is displayed as the option’s text.

  • Each option’s key is set to the country’s id and value is set to the country’s name.

  • The key helps React manage the list efficiently when re-rendering.

The Cities dropdown is conditionally rendered based on the selected country. If the 'Other' country option is chosen, a text input field is displayed for the user to specify the country. Otherwise, if a valid country is selected, a Cities dropdown with relevant options is shown.

{selectedCountry === 'Other' ? (
        <>
          <label htmlFor="other-country" className='font-bold'>Please specify the country: label>
          <input
            id="other-country"
            type="text"
            value={otherCountry}
            onChange={handleOtherCountryChange}
            placeholder="Enter country name"
          />
        
      ) : (
        selectedCountry && (
          <>
            <label htmlFor="city" className='font-bold'>Select City: label>
            <select id="city" value={selectedCity} onChange={handleCityChange}>
              <option value="">Select a cityoption>
              {availableCities.map((city, index) => (
                <option key={index} value={city}>
                  {city}
                option>
              ))}
            select>
          
        )
      )
}

Additionally:

  • We check if selectedCountry is the ‘Other’ option and display a text input.

  • The text input has a otherCountry state and the handleOtherCountryChange handler function attached to it.

  • We control the city