So, in my code looks like setData works fine and gives the fetched data to my state. However it doesn’t work at fist render. But if I cahange something in the code website will be rendered again and country name is gonna show up on the screen just how I wanted.
But this error keeps popping up:
Uncaught TypeError: Cannot read properties of undefined (reading ‘common’)
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
function Country() {
const { countryName } = useParams();
const [data, setData] = useState([]);
const [country, setCountry] = useState({});
useEffect(() => {
fetch('https://restcountries.com/v3.1/all')
.then(resp => resp.json())
.then(datas => setData(datas));
}, [])
useEffect(() => {
setCountry(data.find(a => a.name.common.toLowerCase() == countryName.replaceAll("-", " ")));
}, [data])
return (
<>
{
<h1>{country.name.common}</h1>
}
</>
)
}
export default Country
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
>Solution :
It means that country.name is undefined (and not an object with common property).
On initial render country is {} (an empty object).
So, country.name returns undefined.
And undefined does not have common property. Hence, the error.
So, a good rule of thumb before accessing a property would be to check if that property even exists.
<h1>{country?.name?.common}</h1>
Most of the time, you don’t want to display tags if there is no data.
So, you would like to do something like this.
Markup after && will be rendered only if expression before it, is truthy value.
{country?.name?.common && (
<h1>{country.name.common}</h1>
)}