Home > Software engineering >  How exactly data in useEffect work on page load
How exactly data in useEffect work on page load

Time:09-29

I am fetching data from Firebase when the page loads with useEffect. I want to use socialLinks state in the application like socialLinks.instagram but I am getting this error " Cannot read properties of undefined (reading 'instagram') " .When I assign socialLinks one by one and assign them in the useEffect and use in the page that doesn't give an error. Can anyone explain why I need to assign them one by one instead read from socialLinks.instagram .You can also find my firebase data image below.

  const [socialLinks, setSocialLinks] = useState();
  const [instagram, setInstagram] = useState();
  const [tiktok, setTiktok] = useState();
  const [youtube, setYoutube] = useState();
  useEffect(() => {
    const getSocialLinks = async () => {
      const docRef = doc(socialLinksCol, "24STOxvBEmCezY16LD");
      const fireStoreData = await getDoc(docRef);
      setSocialLinks(fireStoreData.data()); // I can't use this data in <a>
      setYoutube(fireStoreData.data().youtube);  // I can use this data in <a>
      setInstagram(fireStoreData.data().instagram);
      setTiktok(fireStoreData.data().tiktok);
    };
    getSocialLinks(); 
  }, []);

console.log(socialLinks)
//output : {instagram: 'https://www.instagram.com/', youtube: 'https://www.youtube.com/', tiktok: 'https://www.tiktok.com/en/'}

//This is where I use the socialLinks in

    <a href={socialLinks.instagram}>Instagram</a> // This give error
    <a href={tiktok}>Tiktok</a> // This is fine
    <a href={youtube}>Youtube</a>

enter image description here

CodePudding user response:

The first time your component renders you set up some empty state.

For example:

const [socialLinks, setSocialLinks] = useState();

results in a variable called socialLinks being declared. And since you passed no argument to useState, socialLinks will be undefined.

Now useEffect will run. It will kick off an async action in the background (not blocking the component from rendering).

While the data is fetching your component will try render the first time. You reference socialLinks.instagram and socialLinks is undefined so you get an error.

You probably want to not render anything until the data has been loaded.

There are multiple ways to do that. If you want the code to work with the html you have right now, just declare the initial state as empty for social links like this:

const [socialLinks, setSocialLinks] = useState({ 
  instagram: '', tiktok: '', youtube: '' 
});

If you just want to check if the data is there yet then you can leave the state as undefined and then check if its available yet when rendering:

if (socialLinks && socialLinks.instagram) {
   return <a href={socialLinks.instagram}>Instagram</a>;
} else {
   return null;
}

Remember that calling setSocialLinks causes a state update so it will re-render the component when the data is there!

  • Related