I have two dispatch actions 1. fetchHomepage and 2. removeHomepage. I want to run removeHomepage action when I click other link on header menu. So I added removeHomepage in Cleanup Function in useEffect but my cleanup function is not running. When I change something and save then it runs. I am using Redux in this React project. Please can anybody help me out.
HEADER COMPONENT -
import React, { useEffect, useState } from "react";
import "./header.css";
import { useDispatch, useSelector } from "react-redux";
import {
fetchHomepage,
removeHomepage,
} from "../../redux/actions/HomepageActions";
import { setBgColor } from "../../redux/actions/HomepageActions";
import { Link } from "react-router-dom";
import { useLocation } from "react-router-dom";
import Skeleton from "../other/skeletons/Skeleton";
const Header = () => {
const dispatch = useDispatch();
const isLoading = useSelector((state) => state.homepageReducer.isLoading);
const header = useSelector((state) => state.homepageReducer.data.navLinks);
const bgColor = useSelector((state) => state.homepageReducer.bgColor);
const { bgColour, borderColor, iconColor } = bgColor;
const product = useSelector((state) => state.addToCartReducer.products);
const { pathname } = useLocation();
const location = pathname;
console.log("component loaded");
useEffect(() => {
console.log("useffect ran");
const changeNavBg = (bgColor) => {
if (window.scrollY > 0) {
dispatch(setBgColor(bgColor));
} else {
dispatch(
setBgColor({
bgColour: "bg-transparent",
borderColor: "",
iconColor: "",
})
);
}
};
window.addEventListener("scroll", () => {
changeNavBg({
bgColour: "bg-black",
borderColor: "border-white",
iconColor: "text-white",
});
});
dispatch(fetchHomepage());
return () => {
console.log("cleanup function ran");
dispatch(removeHomepage());
window.removeEventListener("scroll", changeNavBg);
};
}, []);
if (isLoading) {
return <Skeleton header={"header"} />;
}
return (
<>
<h1>HEADER</h1>
{
<div className="dvHeader">
<nav
className={`navbar navbar-expand-lg ${bgColour} ${
location !== "/" ? "bg-black" : ""
} navbar-light fixed-top`}
>
<div className="container">
<div>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#slideDownMenu"
aria-controls="slideDownMenu"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="">
<i
className={`fa fa-bars ${iconColor} ${
location !== "/" ? "text-white" : ""
} `}
></i>
</span>
</button>
</div>
<div className="order-lg-0">
<Link to="/">
<img
width="50"
src={header && header.logo.url}
className="img-fluid"
alt=""
/>
</Link>
</div>
<div className="order-lg-2 d-lg-none">
<span
className="d-flex"
data-toggle="modal"
data-target="#mobileCartModal"
>
<span className="d-inline-block mr-1">
<i
className={`fa fa-shopping-cart ${iconColor} ${
location !== "/" ? "text-white" : ""
} `}
></i>
</span>
<span
className={`d-inline-block ${iconColor} ${
location !== "/" ? "text-white" : ""
} `}
>
{product.length}
</span>
</span>
</div>
<div
className="collapse navbar-collapse order-lg-1"
id="slideDownMenu"
>
<ul className="navbar-nav mr-auto px-3">
<li className="nav-item">
<Link className="nav-link" to="/products">
Shop
</Link>
</li>
<li className="nav-item dropdown">
<Link
className="nav-link dropdown-toggle"
to="#"
id="navbarDropdown"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Learn
</Link>
<div
className="dropdown-menu"
aria-labelledby="navbarDropdown"
>
<Link className="dropdown-item" to="#">
Process
</Link>
<Link className="dropdown-item" to="#">
About Us
</Link>
<Link className="dropdown-item" to="#">
Blog
</Link>
<Link className="dropdown-item" to="#">
News
</Link>
<Link className="dropdown-item" to="#">
Beyond The Bottle
</Link>
</div>
</li>
<li className="nav-item">
<Link
className="nav-link"
to="#"
data-toggle="modal"
data-target="#loginModal"
>
Login
</Link>
</li>
<li className="nav-item">
<Link
className="nav-link"
to="#"
data-toggle="modal"
data-target="#signupModal"
>
Sign Up
</Link>
</li>
</ul>
<form className="dvSearch my-2 my-lg-0 px-3">
<input
className={`form-control border-top-0 border-right-0 border-left-0 mr-sm-2 ${
window.innerWidth > 991 ? borderColor : ""
} ${location !== "/" ? "border-white" : ""} `}
type="text"
placeholder="Search"
aria-label="Search"
/>
<button className="btn my-2 my-sm-0" type="submit">
<i
className={`fa fa-search ${iconColor} ${
location !== "/" ? "text-white" : ""
} `}
></i>
</button>
</form>
</div>
</div>
</nav>
</div>
}
<div style={{ height: "10000px" }}></div>
</>
);
};
export default Header;
ACTIONS -
//ACTION CREATOR FETCH HOMEPAGE
export const fetchHomepage = () => {
const apiKey = process.env.REACT_APP_API_KEY;
const url = `https://api.json-generator.com/templates/UhZ_20Akrr7T/data?access_token=${apiKey}`;
return async (dispatch, getState) => {
const response = await fetch(url);
const data = await response.json();
dispatch({
type: actionTypes.SET_HOMEPAGE,
payload: data,
});
};
};
// remove homepage
export const removeHomepage = () => {
return {
type: actionTypes.REMOVE_HOMEPAGE,
};
};
//set nav bg color
export const setBgColor = (data) => {
return {
type: actionTypes.SET_NAV_BG_COLOR,
payload: data,
};
};
HOMEPAGE REDUCER-
import { actionTypes } from "../constants/action-types";
const homeiState = {
data: {},
bgColor: {},
isLoading: true,
};
export const homepageReducer = (state = homeiState, { type, payload }) => {
switch (type) {
case actionTypes.SET_HOMEPAGE:
return {
...state,
data: payload,
isLoading: false,
};
case actionTypes.REMOVE_HOMEPAGE:
return {
...state,
isLoading: true,
};
case actionTypes.SET_NAV_BG_COLOR:
return {
...state,
bgColor: payload,
};
default:
return state;
}
};
CodePudding user response:
Add location to dependency array. When the location url will change then your useEffect will run again and then your cleanup function will also run. Please let me know if it helps.
useEffect(() => {
// get header data
dispatch(fetchHeader());
// send object for changing bg colour
window.addEventListener("scroll", () => {
changeNavBg({
bgColour: "bg-black",
borderColor: "border-white",
iconColor: "text-white",
});
});
return () => {
dispatch(removefetchHeader());
// remove changeNavBg event on scroll
window.removeEventListener("scroll", changeNavBg);
};
}, [location]); //add location here
CodePudding user response:
The useEffect's cleanup function is only called before the component unmounts, your Header component is not unmounting, thus it will not be called.
If you want to call removeHomepage, I suggest calling it in the event function when clicking on a header item or creating a new useEffect hook that reacts to changes to a certain redux value.