Global Scoped Variables in useEffect Dependencies? A big NO!

Global Scoped Variables in useEffect Dependencies? A Big NO!Photo by Pavel Neznanov on UnsplashOuter scope values like ‘window.location.pathname’ aren’t valid dependencies because mutating them doesn’t re-render the component. (react-hooks/exhaustive-d…


This content originally appeared on Bits and Pieces - Medium and was authored by Ajay n Jain

Global Scoped Variables in useEffect Dependencies? A Big NO!

Photo by Pavel Neznanov on Unsplash
Outer scope values like ‘window.location.pathname’ aren’t valid dependencies because mutating them doesn’t re-render the component. (react-hooks/exhaustive-deps)

The use case

Let’s say we have to perform an operation on each page and we have to do this whenever the route changes.

As we have to perform the operation on each page component, let’s abstract the logic out into a hook.

Files

index.js files contains Router config with two pages -> Home Page and Other Page.

Home Page and Other Page renders just a text and calls the common useLocation hook.

In useLocation hook, we will perform some operation based on window.location.pathname which is a global scoped variable.

// FILENAME -> index.js

import React from "react";
import { render } from "react-dom";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

import Other from "./components/Other";
import Home from "./components/Home";

// Basic Router to render Home Page and Other Page
const BasicExample = () => (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/other">Other</Link>
</li>
</ul>

<hr />

<Route exact path="/" component={Home} />
<Route path="/other" component={Other} />
</div>
</Router>
);

render(<BasicExample />, document.getElementById("root"));
// FILENAME -> useLocation.js
// This is the hook that we will be running on each page

import { useEffect } from "react";

const useLocation = (pathname) => {
useEffect(() => {
/*
* If the pathname is same as current page path, perform some operation
* For this example, the operation is to alert the user
* only if pathname passed and window.location.pathname are equal
*/
if (pathname === window.location.pathname) {
alert(
`On Page -> , pathname -> ${pathname},
window.location.pathname -> ${window.location.pathname}`
);
}
}, [pathname, window.location.pathname]);
};

export default useLocation;
// Home Page
import React from "react";
import useLocation from "../useLocation";

const Home = () => {
useLocation("/");

return <h2>Home</h2>;
};

export default Home;

// ----------------------------------------------------------------------

// Other Page
import React from "react";
import useLocation from "../useLocation";

const Other = () => {
useLocation("/other");

return <h2>Other</h2>;
};

export default Other;

Interaction

Gif of interaction of navigating across Home Page and Other Page

In the interaction, we can see that, once we land on Home Page, we see an alert of path -> ‘/’ and navigating to Other Page, we see an alert of path -> ‘/other’.

Everything seems to be working fine, so what’s the problem?

The Problem

Let’s modify the code to perform cleanup operation once the effect has finished running.

In the modified code, we will be alerting as part of the cleanup operation.

// FILENAME -> useLocation.js
// This is the hook that we will be running on each page

import { useEffect } from "react";

const useLocation = (pathname) => {
useEffect(() => {
/*
* If the pathname is same as current page path, perform some operation
* For this example, the operation is to alert the user
* only if pathname passed and window.location.pathname are equal
*/
if (pathname === window.location.pathname) {
// MODIFIED CODE HERE -> removed alert from this condition
// doSomeOperation()
}

// MODIFIED CODE HERE -> CLEANUP OPERATION
// Added the same alert here
return () => {
alert(
`On Page -> , pathname -> ${pathname},
window.location.pathname -> ${window.location.pathname}`
);
}
}, [pathname, window.location.pathname]);
};

export default useLocation;

Let’s see the interaction now

Gif of interaction of navigating across Home Page and Other Page showcasing the Problem

When we navigate to Other Page, the Home Page-effect has completed running and runs the cleanup operation.

While we expect both path and pathname to be same, in the alert we have pathname -> ‘/’ and window.location.pathname -> ‘/other’.
This happens because window.location.pathname is mutated by the time cleanup operation has started.

The same thing happens when we navigate back to Home Page from Other Page.

The Solution

Let’s modify the code to not use window.location.pathname in the dependency and instead, use a local variable defined in the hook.

// FILENAME -> useLocation.js
// This is the hook that we will be running on each page

import { useEffect } from "react";

const useLocation = (pathname) => {
// MODIFIED CODE HERE -> Assigned path = window.location.pathname
// Use this variable across the hook
const path = window.location.pathname;

useEffect(() => {
/*
* If the pathname is same as current page path, perform some operation
* For this example, the operation is to alert the user
* only if pathname passed and path are equal
*/
if (pathname === path) {
// doSomeOperation()
}

return () => {
alert(
`On Page -> , pathname -> ${pathname},
window.location.pathname -> ${path}` // Use path instead of window.location.pathname
);
}
}, [pathname, path]);
};

export default useLocation;
Note: It might be a good idea to extract this code into a custom hook called useLocation. You can then use an open-source toolchain like Bit to publish, version, and reuse it across all of your projects with a simple npm i @bit/your-username/use-location. Find out more here, and here. Anyway, moving on.

Let’s see the interaction now

Gif of interaction of navigating across Home Page and Other Page after applying the Fix

After applying the fix, we can see that we get correct and consistent values.

This works because path is a local variable of each hook instance. While it is assigned to window.location.pathname at the init, the reassignment only happens when there is a rerender.
Have you ever faced issues like these! Do let me know in the comments!

Other stories by me

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

Learn more


Global Scoped Variables in useEffect Dependencies? A big NO! was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces - Medium and was authored by Ajay n Jain


Print Share Comment Cite Upload Translate Updates
APA

Ajay n Jain | Sciencx (2023-02-16T09:41:33+00:00) Global Scoped Variables in useEffect Dependencies? A big NO!. Retrieved from https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/

MLA
" » Global Scoped Variables in useEffect Dependencies? A big NO!." Ajay n Jain | Sciencx - Thursday February 16, 2023, https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/
HARVARD
Ajay n Jain | Sciencx Thursday February 16, 2023 » Global Scoped Variables in useEffect Dependencies? A big NO!., viewed ,<https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/>
VANCOUVER
Ajay n Jain | Sciencx - » Global Scoped Variables in useEffect Dependencies? A big NO!. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/
CHICAGO
" » Global Scoped Variables in useEffect Dependencies? A big NO!." Ajay n Jain | Sciencx - Accessed . https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/
IEEE
" » Global Scoped Variables in useEffect Dependencies? A big NO!." Ajay n Jain | Sciencx [Online]. Available: https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/. [Accessed: ]
rf:citation
» Global Scoped Variables in useEffect Dependencies? A big NO! | Ajay n Jain | Sciencx | https://www.scien.cx/2023/02/16/global-scoped-variables-in-useeffect-dependencies-a-big-no/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.