0

I have a react app that has a "Bread Crumb Header" component, the data for this component comes from an API end point.

I use the bread crumb header component inside multiple components within the app, and based on the current path/window.location the bread crumb component will get the data from the API and render the correct HTML via JSX.

The problem I have is when I navigate to different paths / window.location's within the application the bread crumb component data doesn't update.

This is what the bread crumb 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);
        };
    
        useEffect(() => {
            getBreadCrumbData();
        }, []);
    
        return (
            <div>
    
                <BreadCrumbTitleSection backgroundUrl={breadCrumbData.BreadCrumbBgImage}>
                    <div className="container">
                        <div className="row no-gutters">
                            <div className="col-xs-12 col-xl-prefix-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;

and this is an example of how I am using it inside other components:

import React, { useContext } from 'react';
import { useParams } from "react-router-dom";
import { MenuContext } from '../context/menuContext';
import RenderCmsComponents from '../../components/RenderCmsComponents/';
import BreadCrumbHeader from '../../components/BreadCrumbHeader/';
import { CategorySection, CategoryContainer, CategoryItemCard, CategoryItemCardBody, CategoryItemCardImg, CategoryItemTitle, CategoryRow, AddToCartButton, ProductDescription} from './categoryStyle';

 
function Category() {
    const [categoryItems] = useContext(MenuContext);
    const { id } = useParams();
    const category = categoryItems.find(element => element.CategoryName.toLowerCase() === id.toLowerCase());
    var dynamicProps = [];

    {
        category && category.Products.map(productItem => (

            dynamicProps.push(productItem.ProductOptions.reduce((acc, { OptionName, OptionsAsSnipCartString }, i) => ({
                ...acc,
                [`data-item-custom${i + 1}-name`]: OptionName,
                [`data-item-custom${i + 1}-options`]: OptionsAsSnipCartString
            }), {}))));
    }

    return (
        <div>

            <BreadCrumbHeader /> << HERE IT IS 

        <CategorySection backgroundurl="/images/home-slide-4-1920x800.jpg" fluid>
                <CategoryContainer>
                        <CategoryRow>
                            {category && category.Products.map((productItem, i) => (

                                <CategoryItemCard key={productItem.ProductId}>
                                    <CategoryItemTitle>{productItem.ProductName}</CategoryItemTitle>

                                    <CategoryItemCardBody>
                                        <ProductDescription>{productItem.Description}</ProductDescription>

                                        <div>
                                            <CategoryItemCardImg src={productItem.ProductImageUrl} alt={productItem.ProductName} />
                                        </div>
                                       
                                           
                                    </CategoryItemCardBody>


                                    <AddToCartButton
                                        data-item-id={productItem.ProductId}
                                        data-item-price={productItem.Price}
                                        data-item-url={productItem.ProductUrl}
                                        data-item-description={productItem.Description}
                                        data-item-image={productItem.ProductImageUrl}
                                        data-item-name={productItem.ProductName}
                                        {...dynamicProps[i]}>
                                        ADD TO CART   {productItem.Price}
                                    </AddToCartButton>
         
                                </CategoryItemCard>
                            ))}
                        </CategoryRow>
                </CategoryContainer>
            
         </CategorySection>


            <RenderCmsComponents />
        </div>
    );
}
export default Category;

I found this post on stack overflow: Why useEffect doesn't run on window.location.pathname changes?

I think this may be the solution to what I need, but I don't fully understand the accepted answer.

Can someone breakdown to be how I can fix my issue and maybe give me an explanation and possible some reading I can do to really understand how hooks work and how to use them in my situation.

5
  • Creating a custom hook is the best solution to your problem. Commented Jun 2, 2022 at 10:56
  • @RitikBanger - How? Commented Jun 2, 2022 at 10:57
  • can you try to add location.pathname to useEffect deps? Commented Jun 2, 2022 at 10:59
  • let me know if it works I'll post it as an answer Commented Jun 2, 2022 at 11:00
  • @Oro - Not sure what you mean when you say "deps" I'm very new to React, ifyou could post a more comprehensive answer I will try what you suggest out. Commented Jun 2, 2022 at 11:07

1 Answer 1

1

It seems that you should re-call getBreadCrumbData every time when location.pathname was changed. In the code below I've added location.pathname to useEffect dependency list

        const location = useLocation();
    
        const [breadCrumbData, setBreadCrumbData] = useState([]);
    
        const getBreadCrumbData = async () => {
            const breadCrumbHeaderResponse = await API.fetchBreadCrumbHeader(location.pathname);
            setBreadCrumbData(breadCrumbHeaderResponse);
        };
    
        useEffect(() => {
            getBreadCrumbData();
        }, [location.pathname]); // <==== here
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.