Home > database >  Cleanup Function is not running in useEffect in React Redux
Cleanup Function is not running in useEffect in React Redux

Time:04-21

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.

  • Related