Home > Enterprise >  REST Countries API Call Failing With Router, useParams
REST Countries API Call Failing With Router, useParams

Time:12-19

currently creating a project with the REST Countries API and it's my first time using Router, having a bit of an issue with an API call that is supposed to grab a single country when clicked. For quick reference I uploaded a sandbox here

Routes are set up in App like this:

function App() {
  return (
    <main>
      <Routes>
        <Route path="/" element={<CountriesHome />} />
        <Route path="/countrydetail/:countryName" element={<CountryDetail />} />
      </Routes>
    </main>
  );
}

CountriesHome.js then has an onClick on each country in the homepage that uses navigate:

<section
   className="flex flex-col cursor-pointer"
   key={index}
   onClick={() => navigate(`/countrydetail/${cca2.toLowerCase()}`, {})
   }
>

And inside CountryDetail, I'm trying to useParams to call a specific country, in this case the one clicked by the user, from the API


let { countryName } = useParams();

  const [country, setCountry] = useState();

  const getCountry = async () => {
    try {
      const response = await fetch(
        `https://restcountries.com/v3.1/alpha/${countryName}`
      );
      const data = await response.json();
      setCountry(data);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    getCountry();
  }, [countryName]);

However, I'm just not getting the results I'm expecting with this one, country is returning as undefined and I cannot destructure and render its values.

CodePudding user response:

Because country is an array, so I changed your code like:

const CountryDetail = () => {
  let navigate = useNavigate();
  let { countryName } = useParams();

  const [country, setCountry] = useState([]);

  const getCountry = async () => {
    try {
      const response = await fetch(
        `https://restcountries.com/v3.1/alpha/${countryName}`
      );
      const data = await response.json();
      if (data) {
        setCountry(data);
      }
    } catch (error) {
      console.log(error);
    } finally {
    }
  };

  useEffect(() => {
    getCountry();
  }, [countryName]);

  return (
    <div className="w-11/12 mx-auto grid justify-items-center grid-cols-1 md:grid-cols-3  md:gap-10 lg:grid-cols-4">
      <div className="w-80 h-56 mb-4 bg-slate-900"></div>
      {country?.map((val) => (
        <div>
          <section className="justify-self-start pl-4 mb-6">
            <h1 className="font-extrabold text-lg mb-4 ">
              {val?.name?.common}
            </h1>
            <h5>
              <span className="font-semibold">Native Name: </span>
              {val?.name?.official}
            </h5>
            <h5>
              <span className="font-semibold">Population: </span>
              {val?.population}
            </h5>
            <h5>
              <span className="font-semibold">Region: </span>
              {val?.region}
            </h5>
            <h5>
              <span className="font-semibold">Sub Region: </span>
              {val?.subregion}
            </h5>
            <h5>
              <span className="font-semibold">Capital: </span>
              {val?.capital}
            </h5>
          </section>

          <section className="justify-self-start pl-4">
            <h5>
              <span className="font-semibold">Top Level Domain: </span>
              {val?.tld}
            </h5>
            <h5>
              <span className="font-semibold">Currencies: </span>
              {val?.currencies &&
                Object.values(val?.currencies).map((currency) => {
                  return <span>{currency.name}, </span>;
                })}
            </h5>
            <h5>
              <span className="font-semibold">Languages: </span>
              {val?.languages &&
                Object.entries(val?.languages).map(([key, value]) => {
                  return <span className="m-1">{value}</span>;
                })}
            </h5>
          </section>

          <section className="justify-self-start pl-4 mb-6 ">
            <h3 className="font-semibold text-lg">Border Countries: </h3>
            {val?.borders &&
              val?.borders.map((country) => {
                return (
                  <button className="w-28 py-2 m-2 shadow-[0px_0px_4px_1px_rgba(0, 0, 0, 0.104931)] border-solid border-2 rounded-sm">
                    {country}
                  </button>
                );
              })}
          </section>
        </div>
      ))}
    </div>
  );
};

//

export default CountryDetail;
  • Related