'Uncaught TypeError: Cannot read properties of undefined (reading 'common')
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
const CountryDetail = () => {
const {countryname}=useParams();
const[countrydet,setCountry]=useState([]);
useEffect(()=>{
const url=`https://restcountries.com/v3.1/name/${countryname}`;
fetch(url)
.then(res=>res.json())
.then(data=>setCountry(data))
},[])
return (
<div style={{textAlign: 'center'}}>
<h3>This is country details : {countryname}</h3>
<h4>{countrydet.name.common}</h4>
<h4>{countrydet.continents}</h4>
</div>
);
};
export default CountryDetail;
but there is a element in object {"name":{"common":"Bangladesh","official":"People's Republic of Bangladesh","nativeName":{"ben":{"official":"বাংলাদেশ গণপ্রজাতন্ত্রী","common":"বাংলাদেশ"}}}
Solution 1:[1]
When the component first renders, the asynchronous API call and setting of state hasn't happened yet, so countrydet
is undefined.
<h3>This is country details : {countryname}</h3>
<h4>{countrydet?.name?.common}</h4>
<h4>{countrydet?.continents}</h4>
This should work, and here's the MDN reference for optional chaining.
or alternatively, you could wrap the whole block in a conditional, something like this:
<h3>This is country details : {countryname}</h3>
{ countrydet?.name?.common && countrydet?.continent ?
<>
<h4>{countrydet?.name?.common}</h4>
<h4>{countrydet?.continents}</h4>
</>
:
<></>
}
Solution 2:[2]
- Firstly, set an initial state for
countrydet
. - Then correctly unwrap the response from the fetch request.
.then(([data]) => setCountry(data));
- Check if the
countryname
parameter is set before executing the fetch request. - Check if
countrydet
is defined before trying to access it's properties.
const CountryDetail = () => {
const { countryname } = useParams();
const [countrydet, setCountry] = useState(undefined);
useEffect(() => {
if (countryname) {
const url = `https://restcountries.com/v3.1/name/${countryname}`;
fetch(url)
.then((res) => res.json())
.then(([data]) => setCountry(data));
}
}, [countryname]);
return (
<div style={{ textAlign: "center" }}>
<h3>This is country details : {countryname}</h3>
{countrydet && (
<>
<h4>{countrydet.name.common}</h4>
<h4>{countrydet.continents}</h4>
</>
)}
</div>
);
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Ralph W |