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;