Picture this: you’re crafting a dynamic website, and naturally, you’re incorporating the much-needed scroll event. But here’s the catch — if you don’t use the scroll event listener strategically, brace yourself for an onslaught of component rerenders. After all, who wants their meticulously crafted components to reload needlessly as users casually traverse the page?
Let’s write some code to understand better the problem and try to solve it.
Step 1: Setting the Stage
Let’s establish our foundation. Here’s a glimpse of the initial folder structure:
.
├── src
│ ├── app
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ ├── page.module.css
│ │ ├── page.tsx
│ └── hooks
│ └── useScroll.ts
└── [..]
Step 2: Introducing useScroll
Here is the useScroll
hook, that has a scrollPosition
state variable that gets updated when the window is scrolling.
import { useState, useEffect } from "react";
interface ScrollPosition {
x: number;
y: number;
}
const useScroll = (): ScrollPosition => {
const [scrollPosition, setScrollPosition] = useState<ScrollPosition>({
x: 0,
y: 0,
});
const handleScroll = () => {
setScrollPosition({
x: window.scrollX,
y: window.scrollY,
});
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return scrollPosition;
};
export default useScroll;
Step 3: Styling
Before building the page.tsx
file, we will add some basic styles in the page.module.css
.
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100vw;
padding: 2.5rem 6.25rem;
background-color: red;
}
.header.active {
background-color: blue;
}
.navList {
display: flex;
align-items: center;
column-gap: 1.5rem;
}
.navItem {
color: white;
}
Also, in the globals.css
file, you should use the following styles.
* {
box-sizing: border-box…