Last updated: Apr 7, 2024
Reading time·5 min
div
element in Reactwindow
object in Reactdiv
element in ReactTo handle the onScroll event in React:
onScroll
prop on an element to listen for the scroll
event.event.currentTarget.scrollTop
property to get the number of
pixels the element is scrolled vertically.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> ); }
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.
const handleScroll = event => { setScrollTop(event.currentTarget.scrollTop); };
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.
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.
window
object in ReactYou can use the
addEventListener() method
to handle the onScroll
event on the window
object.
scroll
event listener to the window
object in your useEffect
hook.window.scrollY
property to get the number of pixels that the
document is vertically scrolled.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;
The addEventListener
method takes the following 2 arguments:
Name | Description |
---|---|
type | the type of the event to listen for |
listener | a 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.
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.
useEffect
hook is called when the component unmounts.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:
Name | Description |
---|---|
type | the type of event for which to remove an event listener |
listener | the 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.
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.
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;
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 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.
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;
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.
Now that we know that the correct type for the onScroll
event is
React.UIEvent<HTMLDivElement, UIEvent>
, we can extract our handler function.
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;
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.