In our previous post, we learned about the useRef()
hook, which helps us persist values to avoid unnecessary re-renders. Today, we'll delve into another practical application of useRef()
: tracking the previous value of a variable.
Tracking the previous value of a variable can be useful in many ways. For instance, it can help us detect changes in state and trigger certain actions accordingly. It can also aid in comparing the current value with the previous value to determine if there have been any changes.
This is especially handy when implementing undo/redo functionality, where you need to compare the current value of something to its previous value. By being able to easily access the previous value, we can compare it with the current value and determine if any changes have been made.
Moreover, tracking the previous value can be helpful when dealing with form inputs or user interactions. By keeping track of the previous value, we can easily revert back to it if needed or validate against it.
Overall, there are numerous scenarios where tracking the previous value of a variable can come in handy, making our code more robust and efficient.
Keeping track of previous values with a custom hook
We'll create a custom hook called usePrevious
to keep track of the previous value of a state in React.
This hook uses a ref to store the previous value, which gets updated every time the component re-renders. Here's an example implementation of the usePrevious
hook:
import * as React from 'react';
const usePrevious = (value) => {
const ref = React.useRef();
React.useEffect(() => {
ref.current = value;
});
return ref.current;
};
In this example, we're creating a new ref with useRef
to store the previous value. Then, we're using useEffect
to update this ref every time the component re-renders. Finally, we're returning the current value of the ref using return ref.current
.
By using this hook in your components, you can easily access and compare previous values without the hassle of manually storing them yourself. This can greatly simplify your code and make it easier to understand.
Discovering scroll direction
Let's explore some useful applications of the usePrevious
hook. First, we'll discuss detecting the scroll direction.
Detecting scroll direction is commonly used for infinite scrolling. By knowing whether the user is scrolling up or down, we can fetch data accordingly and append it to the existing list. This boosts performance by reducing the amount of data that needs to be loaded at once.
Another use case is for scroll-based animations. You may want to trigger an animation when a certain element comes into view while scrolling down, but not when scrolling up. By detecting the scroll direction and position, you can easily determine when to trigger the animation.
Additionally, detecting scroll direction can be useful in creating custom navigation menus that change based on the user's scroll position. For example, you could have a menu that appears at the top of the page when scrolling up and disappears when scrolling down, providing a more immersive user experience.
Overall, detecting scroll direction can be creatively used in many ways to enhance your web applications.
To track changes in the scroll position, we can use the usePrevious
hook. This hook helps us keep track of the previous value of the scroll position, so we can determine whether it has increased or decreased. To get started, we need to create a state variable that will hold our current scroll position.
const [scrollPosition, setScrollPosition] = React.useState(0);
To figure out where the user is currently scrolling, we need to handle the scroll
event. In our example, we create a function called handleScroll
that updates the scrollPosition
state variable with the current value of window.scrollY
.
const handleScroll = () => setScrollPosition(window.scrollY);
Next, we use the useEffect
hook to add an event listener for the scroll
event. This listener calls our handleScroll
function each time the event occurs. We also remove the listener when our component unmounts to avoid any memory leaks.
React.useEffect(() => {
document.addEventListener("scroll", handleScroll);
return () => {
document.removeEventListener("scroll", handleScroll);
};
}, []);
Good practice
To improve the performance of your scroll handler, it's recommended to use either debounce or throttle. This is because the
scroll
event can fire multiple times per second, which can slow down your website or app if your handler function is doing a lot of work.Debouncing and throttling are techniques that limit the number of times a function is called based on a certain time
interval. Debouncing waits until a certain amount of time has passed since the last time the function was called before calling it again. Throttling, on the other hand, only calls the function once every set interval. These techniques can help ensure that your scroll handler is efficient and doesn't negatively impact the user experience.In our example, we'll use the
throttle
function from the lodash library to control the frequency of ourhandleScroll
function.import { throttle } from 'lodash'; const handleScrollThrottled = throttle(handleScroll, 100); React.useEffect(() => { document.addEventListener("scroll", handleScrollThrottled); return () => { document.removeEventListener("scroll", handleScrollThrottled); }; }, []);
In this example, we import the
throttle
function from lodash to optimize our scroll event handling. We create a new function,handleScrollThrottled
, by passing in our originalhandleScroll
function and an interval of 100 milliseconds. Then, we add an event listener for thescroll
event using our new throttled function. Finally, we remove the listener when our component unmounts.By using throttling or debouncing in your scroll handlers, you can significantly improve your component's performance, reducing unnecessary re-renders and making your user experience smoother.
Next, we can use the usePrevious
hook to retrieve the previous value of our scroll position.
const previousScrollPosition = usePrevious(scrollPosition);
Now that we've stored both our current and previous values as variables, we can compare them in an effect hook that runs every time the current value changes.
React.useEffect(() => {
if (previousScrollPosition < scrollPosition) {
console.log("Scroll down");
} else if (previousScrollPosition > scrollPosition) {
console.log("Scroll up");
}
}, [scrollPosition, previousScrollPosition]);
In this example, we log "Scroll down" when the current scroll position is greater than the previous one, and "Scroll up" when it's less. By using this technique, we can quickly detect the scrolling direction and perform actions accordingly.
If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!
If you want more helpful content like this, feel free to follow me:
Top comments (0)