Skip to content
Advertisement

Looping/Map/Iterating over object results in Cannot read properties of undefined (reading ‘map’) error, but data is present

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:

enter image description here

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 => 
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement