React + TypeScript: Handling onScroll event

Last updated on March 3, 2023 A Goodman Loading... 2 comments


The onScroll event occurs when an element’s scrollbar is being scrolled.

This article walks you through an end-to-end example of handling the onScroll event in a React application. We’ll use TypeScript and modern features of React including hooks and functional components. You won’t see old-fashioned stuff like class-based components or things relate to them.

The Complete Example

The simple app we are going to make contains an orange box, a list, and a progress bar. The box has a fixed height of 400px. The list resides inside the box and displays a large number of items. The progress bar indicates how many items were viewed (or more precisely, the percentage of items viewed) by the user when they scrolled down.


A demo is worth more than a thousand words. Here’s how our app works:

The Code

1. Create a new React project by executing the following command:

npx create-react-app kindacode_react_ts --template typescript

The project name is totally up to you.

2. The full source code in src/App.tsx with explanations:

// App.tsx
import React, { useState } from "react";

// Generate some dummy data
const DUMMY_DATA = Array.from({ length: 100 }, (x, i) => {
  return {
    id: i,
    title: `Item ${i}`,

const App = () => {
  const [progress, setProgress] = useState(0);

  // This function is triggered when the user scroll
  const scrollHandler = (event: React.UIEvent<HTMLDivElement>) => {
    const containerHeight = event.currentTarget.clientHeight;
    const scrollHeight = event.currentTarget.scrollHeight;

    const scrollTop = event.currentTarget.scrollTop;
    setProgress(((scrollTop + containerHeight) / scrollHeight) * 100);

  return (
      {/* The container */}
      <div style={styles.container} onScroll={scrollHandler}>
        {/* The list */}
        <div style={styles.list}>
          { => (
            // A single item
            <div style={styles.item} key={}>

      {/* The progress bar */}
      <div style={styles.progressBar}>
        <div style={{ ...styles.progressValue, width: `${progress}%` }}></div>
      <p style={styles.text}>{progress.toFixed(2)}%</p>

// Styling
const styles = {
  container: {
    width: 500,
    height: 400,
    margin: "30px auto",
    overflowY: "auto",
    overflowX: "hidden",
    background: "orange",
  list: {
    width: "100%",
  item: {
    margin: "20px 25px",
    padding: "30px 20px",
    boxShadow: "0 2px 4px #999",
    background: "purple",
    fontSize: "18px",
    textAlign: "center",
    color: "#fff",
  progressBar: {
    width: 600,
    height: 20,
    margin: "auto",
    backgroundColor: "#bbb",
  progressValue: {
    height: "100%",
    backgroundColor: "blue",
  text: {
    textAlign: 'center'
} as const;

export default App;

3. Run the project:

npm start

And go to http://localhost:3000 to check the result.


We’ve built a simple app to get a better understanding of the onScroll event in React and TypeScript. If you’d like to explore more new and interesting things in modern React and frontend development, take a look at the following articles:

You can also check our React category page and React Native category page for the latest tutorials and examples.

Notify of
Inline Feedbacks
View all comments
10 months ago

calculation formula is wrong
need to do so

setProgress((scrollTop / (scrollHeight - containerHeight)) * 100);

Related Articles