'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