I have a react component that gets data from an API end point. For the purposes of debugging when I call the API I log the result of the API call to the console and it looks like this:
The problem I have is that when I try to render the BreadCrumbLinks Property in my component I get this error:
TypeError: Cannot read properties of undefined (reading ‘map’)
at BreadCrumbHeader
I am getting an “Undefined” error, but I know that the data is present because I can read and render all of the other fields (for example BreadCrumbBgImage
).
Also, if I comment out the map/loop the rest of the data is displayed correctly when the page loads. Then if I uncomment it out and save the file the data for the map/loop now shows correctly.
I can only assume that the code is trying to render the contents of the loop before it has been loaded.
This is what the code for the component looks like:
import React, { useState, useEffect } from 'react'; import API from "../../API"; import { useLocation } from 'react-router-dom'; import { BreadCrumbTitleSection, SubtitleSection, Subtitle } from './breadCrumbHeaderStyle'; import { Breadcrumb } from 'react-bootstrap'; function BreadCrumbHeader() { const location = useLocation(); const [breadCrumbData, setBreadCrumbData] = useState([]); const getBreadCrumbData = async () => { const breadCrumbHeaderResponse = await API.fetchBreadCrumbHeader(location.pathname); setBreadCrumbData(breadCrumbHeaderResponse); console.log("OUT-PUT-OF-API-CALL"); console.log(breadCrumbHeaderResponse); console.log("END-OF-OUT"); }; useEffect(() => { getBreadCrumbData(); }, [location.pathname]); return ( <div> <BreadCrumbTitleSection backgroundUrl={breadCrumbData.BreadCrumbBgImage}> <div className="container"> <div className="row no-gutters"> <div className="col-xs-12 col-xl-preffix-1 col-xl-11"> <h1 className="h3 text-white">{breadCrumbData.BreadCrumbTitle}</h1> <Breadcrumb> {breadCrumbData.BreadCrumbLinks.map(breadCrumbLink => ( <Breadcrumb.Item href={breadCrumbLink.LinkUrl} key={breadCrumbLink.Id} active={breadCrumbLink.IsActive}> {breadCrumbLink.LinkText} </Breadcrumb.Item> ))} </Breadcrumb> </div> </div> </div> </BreadCrumbTitleSection> <SubtitleSection> <Subtitle> {breadCrumbData.SubTitle}</Subtitle> </SubtitleSection> </div> ); } export default BreadCrumbHeader;
Can anyone explain what is going on here and how I can solve i?
Advertisement
Answer
You are trying to map data before its fetched, so its an empty array (initial value of breadCrumbData state). You should use optional chaining:
{breadCrumbData?.BreadCrumbLinks?.map(breadCrumbLink =>