How to Create 3(country,state and city) dropdowns that populates data with each other in react js

Viewed 8061

I want to create 3 dropdowns such as country,state,city.Based on selection in country option it should populate the state and based on country and state selected option the city dropdown should populate itself in react js. Thanks in Advance

i want add more states here in the usa country

  componentDidMount() {
    this.setState({
      countries: [
        {
          name: "Germany",
          states: [
            {
              name: "A",
              cities: ["Duesseldorf", "Leinfelden-Echterdingen", "Eschborn"]
            }
          ]
        },
        { name: "Spain", states: [{ name: "B", cities: ["Barcelona"] }] },

        { name: "USA", states: [{ name: "C", cities: ["Downers Grove"] }] },
        {
          name: "Mexico",
          states: [{ name: ["D", "F", "H"], cities: ["Puebla"] }]
        },
        {
          name: "India",
          states: [
            { name: "E", cities: ["Delhi", "Kolkata", "Mumbai", "Bangalore"] }
          ]
        }
      ]
    });
  }

  changeCountry(event) {
    this.setState({ selectedCountry: event.target.value });
    this.setState({
      states: this.state.countries.find(
        (cntry) => cntry.name === event.target.value
      ).states
    });
  }

  changeState(event) {
    this.setState({ selectedState: event.target.value });
    const stats = this.state.countries.find(
      (cntry) => cntry.name === this.state.selectedCountry
    ).states;
    this.setState({
      cities: stats.find((stat) => stat.name === event.target.value).cities
    });
  }

i want to display more states and city in one country (3 dropdowns)

  render() {
    return (
      <div id="container">
        <h2>Cascading or Dependent Dropdown using React</h2>

        <div>
          <label>Country</label>
          <select
            placeholder="Country"
            value={this.state.selectedCountry}
            onChange={this.changeCountry}
          >
            <option>--Choose Country--</option>
            {this.state.countries.map((e, key) => {
              return <option key={key}>{e.name}</option>;
            })}
          </select>
        </div>

        <div>
          <label>State</label>
          <select
            placeholder="State"
            value={this.state.selectedState}
            onChange={this.changeState}
          >
            <option>--Choose State--</option>
            {this.state.states.map((e, key) => {
              return <option key={key}>{e.name}</option>;
            })}
          </select>
        </div>

        <div>
          <label>City</label>
          <select placeholder="City">
            <option>--Choose City--</option>
            {this.state.cities.map((e, key) => {
              return <option key={key}>{e}</option>;
            })}
          </select>
        </div>
      </div>
    );
  }
}
1 Answers

Your solution is in a good direction. Though you can simplify it. Here's an example on how you can do it using React Hooks.

https://codesandbox.io/s/sweet-monad-kzp3p?file=/src/App.js

We start off by creation 3 states:

  const [selectedCountry, setSelectedCountry] = React.useState();
  const [selectedState, setSelectedState] = React.useState();
  const [selectedCity, setSelectedCity] = React.useState();

  const availableState = data.countries.find((c) => c.name === selectedCountry);
  const availableCities = availableState?.states?.find(
    (s) => s.name === selectedState
  );

Normally their values will be undefined. Every time you make a selection in the dropdown, we can update them. When updated, we can use the data to find the corresponding states (in availableState). And if a state has been selected, we can use that property to find the cities for this state.

The ?.states is a null check. So if the availableState has not been set yet, we won't try to call any functions on it.

This way we can use the same properties for both rendering and finding the correct data. Removing a lot of update complexity.

The render would look like this:

return (
    <div id="container">
      <h2>Cascading or Dependent Dropdown using React</h2>

      <div>
        <label>Country</label>
        <select
          placeholder="Country"
          value={selectedCountry}
          onChange={(e) => setSelectedCountry(e.target.value)}
        >
          <option>--Choose Country--</option>
          {data.countries.map((value, key) => {
            return (
              <option value={value.name} key={key}>
                {value.name}
              </option>
            );
          })}
        </select>
      </div>

      <div>
        <label>State</label>
        <select
          placeholder="State"
          value={selectedState}
          onChange={(e) => setSelectedState(e.target.value)}
        >
          <option>--Choose State--</option>
          {availableState?.states.map((e, key) => {
            return (
              <option value={e.name} key={key}>
                {e.name}
              </option>
            );
          })}
        </select>
      </div>

      <div>
        <label>City</label>
        <select
          placeholder="City"
          value={selectedCity}
          onChange={(e) => setSelectedCity(e.target.value)}
        >
          <option>--Choose City--</option>
          {availableCities?.cities.map((e, key) => {
            return (
              <option value={e.name} key={key}>
                {e}
              </option>
            );
          })}
        </select>
      </div>
    </div>
  );
Related