Handle the onScroll event in React (with examples)

avatar
Borislav Hadzhiev

Last updated: Apr 7, 2024
5 min

banner

# Table of Contents

  1. Handle the onScroll event on a div element in React
  2. Handle the onScroll event on the window object in React
  3. Type the onScroll event of an element in React (TypeScript)

# Handle the onScroll event on a div element in React

To handle the onScroll event in React:

  1. Set the onScroll prop on an element to listen for the scroll event.
  2. Provide an event handler function.
  3. Access the event.currentTarget.scrollTop property to get the number of pixels the element is scrolled vertically.
App.js
import {useState} from 'react'; export default function App() { const [scrollTop, setScrollTop] = useState(0); const handleScroll = event => { setScrollTop(event.currentTarget.scrollTop); }; return ( <div> <h2>Scroll Top: {scrollTop}</h2> <div style={{ border: '3px solid black', width: '400px', height: '100px', overflow: 'scroll', }} onScroll={handleScroll} > {[...Array(20)].map((_, index) => ( <p key={index}>Content {index}</p> ))} </div> </div> ); }

react onscroll div

The code for this article is available on GitHub

We set the onScroll prop on the div element, so every time the user scrolls the horizontal or vertical axis of the div, the handleScroll function gets invoked.

Notice that we used the currentTarget property on the event object to get access to the element.

App.js
const handleScroll = event => { setScrollTop(event.currentTarget.scrollTop); };
The currentTarget property on the event gives us access to the element that the event listener is attached to.

On the other hand, the target property on the event gives us a reference to the element that triggered the event (could be a descendant).

We used the Element.scrollTop property to get the number of pixels the element's content is scrolled vertically.

The last step is to update the state variable using the useState hook.

App.js
setScrollTop(event.currentTarget.scrollTop);

The setScrollTop function takes care of updating the scrollTop state variable every time the scrolls the vertical axis of the div.

If you need to set a conditional initial value for useState, check out this article.

# Handle the onScroll event on the window object in React

You can use the addEventListener() method to handle the onScroll event on the window object.

  1. Add a scroll event listener to the window object in your useEffect hook.
  2. Use the window.scrollY property to get the number of pixels that the document is vertically scrolled.
App.js
import {useEffect, useState} from 'react'; const App = () => { const [scrollTop, setScrollTop] = useState(0); useEffect(() => { const handleScroll = event => { setScrollTop(window.scrollY); }; window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, []); return ( <div> <div style={{ position: 'fixed', padding: '10px 0', top: '0', backgroundColor: 'white', borderBottom: '3px solid black', width: '100%', }} > <h2>Scroll Top: {scrollTop}</h2> </div> <div style={{marginTop: '10rem'}}> {[...Array(100)].map((_, index) => ( <p key={index}>Content {index}</p> ))} </div> </div> ); }; export default App;

react onscroll window

The code for this article is available on GitHub

The addEventListener method takes the following 2 arguments:

NameDescription
typethe type of the event to listen for
listenera function to be invoked when the event is triggered

The scroll event is triggered when the document view has been scrolled.

We passed an empty dependencies array to the useEffect hook because we only want to register the scroll event listener once - when the component mounts.

App.js
useEffect(() => { const handleScroll = event => { setScrollTop(window.scrollY); }; window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, []);

We used the window.scrollY property to update the scrollTop state variable.

The window.scrollY property on the window object returns the number of pixels that the document is currently scrolled vertically.

If you set the onScroll prop on an element, you would use the Element.scrollTop property instead as shown in the previous subheading.

The function we returned from the useEffect hook is called when the component unmounts.
App.js
return () => { window.removeEventListener('scroll', handleScroll); };

We used the removeEventListener() method to remove the event listener that we previously registered.

The removeEventListener method takes the following 2 arguments:

NameDescription
typethe type of event for which to remove an event listener
listenerthe event listener function of the event handler to remove from the event target

The cleanup step is important because we want to make sure we don't have any memory leaks in our application.

The scrollTop property returns the number of pixels that an element's content is scrolled vertically.

If you need to scroll to the bottom of a div, click on the link and follow the instructions.

Want to learn more about scrolling in React? Check out these resources: How to Scroll to an Element on click in React,Scroll to the top of the Page in React.js.

# Type the onScroll event of an element in React (TypeScript)

To type the onScroll event of an element in React, set its type to React.UIEvent<HTMLElement>.

The UIEvent type is used for onScroll events in React. You can access properties on the element the event is attached to on the currentTarget property.

App.tsx
const App = () => { const handleScroll = (event: React.UIEvent<HTMLElement>) => { console.log(event.currentTarget.scrollTop); console.log(event.currentTarget.offsetHeight); }; return ( <div style={{ border: '3px solid black', width: '400px', height: '100px', overflow: 'scroll', }} onScroll={handleScroll} > <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> </div> ); }; export default App;
The code for this article is available on GitHub

We typed the event as React.UIEvent<HTMLElement> because the UIEvent type is used for onScroll events in React.

However, we could have been more specific when typing the event.

# The easiest way to find the type of an event

The easiest way for you to find out what the type of an event is, is to write the event handler inline and hover over the event parameter in the function.

App.tsx
const App = () => { // 👇️ onScroll event is written inline // hover over the `event` parameter with your mouse return ( <div style={{ border: '3px solid black', width: '400px', height: '100px', overflow: 'scroll', }} onScroll={event => console.log(event)} > <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> </div> ); }; export default App;

get type of onscroll event inline

When the event is written inline, I can hover over the event parameter and it shows me what the type of the event is.

TypeScript is able to infer the type of the event when it's written inline.

This is very useful because it works with all events. Simply write a "mock" implementation of your event handler inline and hover over the event parameter to get its type.

Once you know the type of the event, you are able to extract your handler function and type it correctly.

Now that we know that the correct type for the onScroll event is React.UIEvent<HTMLDivElement, UIEvent>, we can extract our handler function.

App.tsx
const App = () => { // 👇️ onScroll event is typed correctly now const handleScroll = (event: React.UIEvent<HTMLDivElement, UIEvent>) => { console.log(event.currentTarget.scrollTop); console.log(event.currentTarget.offsetHeight); }; return ( <div style={{ border: '3px solid black', width: '400px', height: '100px', overflow: 'scroll', }} onScroll={handleScroll} > <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> <p>Content</p> </div> ); }; export default App;
The code for this article is available on GitHub
Note that you can use this approach to get the type of all events, not just onScroll events.

As long as you write the event handler function inline and hover over the event parameter, TypeScript will be able to infer the event's type.

Notice that we used the currentTarget property on the event because we want to access the element that the event listener is attached to.

The target property on the event gives us a reference to the element that triggered the event.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.