1

I am at very beginner level and I 'm stuck on this task.

Tasks

  1. When the page loads, populate a dropdown menu with the results from a GET call to https://xc-countries-api.fly.dev/api/countries/
  2. When a country is selected from the country dropdown, populate a second dropdown with the results from a GET call to https://xc-countries-api.fly.dev/api/countries/<country_code>/states/

I can not get data from second API for states.

Thank you for your time...

import { useState, useEffect } from "react";

const CountriesStates = () => {
    const [countries, setCountries] = useState([]);
    const [states, setStates] = useState([]);
    
    useEffect(() => {
        fetch('https://xc-countries-api.fly.dev/api/countries/')
            .then((response) => {
                return response.json();
            })
            .then((data) => {
                //console.log(data);
                setCountries(data); 
            })
    }, []);

    useEffect(() => {
        
        if(countries === 'default' || countries === '') {
            setStates([]);
        } else {
            fetch(`https://xc-countries-api.fly.dev/api/countries/${countries}/states/`)
                .then((response) => {
                    return response.json();
                })
                .then((data) => {
                    setStates(data);
                })
            }   
    }, [countries]);

    return (
        <>
            <div>
                <select name='countries' id='countries' style={{backgroundColor:'lightblue', borderRadius:'5px', fontSize:'1.3rem', marginRight:'3rem'}}>
                {
                    countries.map((country) => (                    
                            <option key={country.id}>{country.name}</option>                   
                    ))
                }
                </select>         
            </div>

            <div>
                <select name='states' id='states' style={{backgroundColor:'lightblue', borderRadius:'5px', fontSize:'1.3rem', marginRight:'3rem'}}>
                {
                    states.map((state) => (                    
                            <option key={state.id}>{state.name}</option>                   
                    ))
                }
                </select>         
            </div>
        </>
    );
};

export default CountriesStates;
3
  • You are sending all the country state as the API parameter country_code. However, you need to use the selected country's code there. You can try countries[0].code to test. For example, the first country is Australia and its code is AU. Then when you send a request to the URL with these parameters: xc-countries-api.fly.dev/api/countries/AU/states, it returns as you expected. Hope, it's clear Commented Feb 16, 2024 at 21:16
  • @OnurDoğan thank you so much it really helped. when I check it with countries[0].code yes I can see states on second dropdown. Bu I should study more to understand the logic and how to do it I guess. Commented Feb 17, 2024 at 17:33
  • Glad to be helpful to you. As a suggestion, you can create a new state like selectedCountry and then set it when selecting a country from the first (countries) dropdown. Also, need to change the second useEffects dependency to selectedCountry instead of the countries. Then it will be triggered whenever you change selectedCountry and will fetch states for the selected country. It might be a bit complicated to explain, so I will post an answer to explain better Commented Feb 17, 2024 at 20:31

1 Answer 1

0

For the selected country, need to add a new state to store and update it. I added the selectedCountry state and then set it whenever the selected option is changed from the dropdown.
Then, need to fetch states whenever the selected country is selected. For this, need to use selectedCountry instead of countries in the useEffect dependency that fetches the states.

CountriesStates.js: (Added some comment lines)

import { useState, useEffect } from "react";

const CountriesStates = () => {
    const [countries, setCountries] = useState([]);
    const [states, setStates] = useState([]);
    // Store the selected country in a new state
    const [selectedCountry, setSelectedCountry] = useState();
    
    useEffect(() => {
        fetch('https://xc-countries-api.fly.dev/api/countries/')
            .then((response) => response.json())
            .then((data) => {
                setCountries(data); 
                // set the first country as selected automatically 
                setSelectedCountry(data[0]);
            })
    }, []);

    useEffect(() => {
        // If there's no selected country, then prevent sending an API request and clear the states
        if (!selectedCountry) {
           setStates([]);
           return;
        }

        fetch(`https://xc-countries-api.fly.dev/api/countries/${selectedCountry.code}/states/`)
          .then((response) => response.json())
          .then(setStates);
}   
    }, [selectedCountry]); // This useEffect should be rendered whenever the selected country is changed

    return (
        <>
            <div>
                <select 
                    name='countries' 
                    id='countries' 
                    style={{backgroundColor:'lightblue', borderRadius:'5px', fontSize:'1.3rem', marginRight:'3rem'}}
                    onChange={event => setSelectedCountry(countries.find(({ id }) => id.toString() === event.target.value.toString()))}>
                {
                    countries.map((country) => (
                         <option key={country.id} value={country.id}>{country.name}</option>                   
                    ))
                }
                </select>         
            </div>
           {!!states.length &&
              <div>
                  <select name='states' id='states' style={{backgroundColor:'lightblue', borderRadius:'5px', fontSize:'1.3rem', marginRight:'3rem'}}>
                  {
                      states.map((state) => (                    
                              <option key={state.id}>{state.name}</option>                   
                      ))
                  }
                  </select>         
              </div>
           }
        </>
    );
};

export default CountriesStates;

I also created a DEMO LINK to review and test it easily.

Hope, it's clear and helpful.

2
  • 1
    this is so helpful and with that comments which you add helped me to understand why exactly you used codes and what was it for. I am grateful for your help!! Commented Feb 17, 2024 at 23:21
  • I am so glad to be helpful. You're welcome! Commented Feb 18, 2024 at 9:30

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.