Ayo Adesina
Ayo Adesina

Reputation: 2415

Data in React Component Not refreshing when Path/Location changes

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.

Upvotes: 0

Views: 498

Answers (1)

Oro
Oro

Reputation: 2596

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

Upvotes: 1

Related Questions