4

Excuse my lack of knowledge as i am fairly new to ReactJS. I'm trying to create a dynamic Dropdown system where i have The Country DropDown and the cities DropDown, and i want to fetch my data from a const that has multiple arrays in it, here's an example of the const i have:

const countries = {"France":["Paris","Marseille","Lille","Lyon"],
                   "Usa":["New York","San Francisco","Austin","Dallas"]
                  };

I know that i need to use the useState and the useEffect hooks and a function to handle the event changes.

What i'm having a hard time to figure out is how to deal with the data format, especially that the variables inside the const can't be accessed easily, it would've been much easier if the data was in this shape:

const countries =[
                   { name: 'Usa',  cities: ["New York", "San Francisco", "Austin", "Dallas"]},
                   { name: 'France', cities: ["Paris", "Marseille", "Lille", "Lyon"]},
                 ]

But unfortunately the first sample is the shape of data i have to deal with and i can't modify it manually because i have a very large sample of data. So if anyone could just direct me briefly into the steps i should make, i would be very thankful.

1
  • 1
    well always you want to try to minimize the time needed for developing some component especially if your are working in a company and you have delivery date. so searching for library will help you minimizing the time. here multi select library for your need react-select.com Commented Jun 7, 2020 at 0:13

2 Answers 2

5

You can abstract the country in a separate list with the "Object.keys" and use the first one to get the cities. I think in this case you don't need to use "useEffect".

Example here: https://codesandbox.io/s/dropdown-react-p0nj7

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [cities, setCities] = useState([]);
  const [selectedCounty, setSelectedCountry] = useState("");
  const [selectedCity, setSelectedCity] = useState("");

  const countries = {
    France: ["Paris", "Marseille", "Lille", "Lyon"],
    Usa: ["New York", "San Francisco", "Austin", "Dallas"],
    Brazil: ["São Paulo", "Rio de Janeiro", "Salvador"]
  };

  const countryList = Object.keys(countries).map(key => ({
    name: key
  }));

  function handleCountrySelect(e) {
    console.log("Selected country", e.target.value);
    const countrySel = e.target.value;
    const citiesSel = countrySel !== "" ? countries[countrySel] : [];
    setSelectedCountry(countrySel);
    setCities(citiesSel);
    setSelectedCity("");
  }

  function handleCitySelect(e) {
    console.log("Selected city", e.target.value);
    const citiesSel = e.target.value;
    setSelectedCity(citiesSel);
  }

  return (
    <div className="App">
      <h1>Example DropDown Coutries and Cities</h1>

      <div className="Container">
        <select
          name="Countries"
          onChange={e => handleCountrySelect(e)}
          value={selectedCounty}
        >
          <option value="">Select the country</option>
          {countryList.map((country, key) => (
            <option key={key} value={country.name}>
              {country.name}
            </option>
          ))}
        </select>

        <select
          name="Cities"
          onChange={e => handleCitySelect(e)}
          value={selectedCity}
        >
          <option value="">Select the city</option>
          {cities.map((city, key) => (
            <option key={key} value={city}>
              {city}
            </option>
          ))}
        </select>
      </div>
    </div>
  );
}

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, this suits me because i wanted to use Object keys !
3

so,

  • we gotta traverse the countries array and get the list of distinct countries for first dropdown (check useEffect hook)
  • store the selected Country from this first dropdown inside the state in selectedCountry
  • use the selected country to display the relevant cities list (countries[selectedCountry].map... inside return);

relevant JS:

import React, { useState, useEffect } from "react";

const countries = {
  France: ["Paris", "Marseille", "Lille", "Lyon"],
  Usa: ["New York", "San Francisco", "Austin", "Dallas"]
};

const Dropdown = () => {
  const [countryData, setCountryData] = useState(["Usa"]);
  const [selectedCountry, setSelectedCountry] = useState("");

  const checkInsertInArray = newCountry => {
    let findStatus = countryData.find(x => {
      return x === newCountry;
    });
    if (!findStatus) {
      setCountryData([...countryData, newCountry]);
    }
  };

  const countryChange = event => {
    if (event.target.value) {
      setSelectedCountry(event.target.value);
    }
  };

  useEffect(() => {
    Object.keys(countries).forEach(country => {
      checkInsertInArray(country);
    });
  });

  return (
    <>
      <span>Country:</span>
      <select onChange={countryChange}>
        <option value="" />
        {countryData.map(allCountries => {
          return <option value={allCountries}>{allCountries}</option>;
        })}
      </select>
      <br />
      {selectedCountry ? (
        <>
          <span>City:</span>{" "}
          <select>
            <option value="" />
            {countries[selectedCountry].map(allCountries => {
              return <option value={allCountries}>{allCountries}</option>;
            })}
          </select>
        </>
      ) : (
        <span>City: Please select a country first</span>
      )}
    </>
  );
};

export default Dropdown;

working stackblitz here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.