Infinite scrolling in React
All of us casually surfing through the internet, scrolling through our Instagram feeds, binging Youtube recommendation videos, never even realize that we use infinite scrolling so intuitively on our phones and laptops every single day. It's the ease of its use that makes us never question - how is infinite scrolling actually implemented? Until we actually have to implement it somewhere. It might just take us one thumb to use infinite scrolling, but there is quite a bit of work that goes into implementing it. So in this article I'll show you two of ways to implement infinite scrolling. Let's begin!!
Let's try to make an app called ColorFool which generates tiles of random colors after a small delay of 500ms as we scroll to the bottom. Here is a glimpse of it -
NOTE - The working code is available in this repository.
For simplicity’s sake, let’s just use create-react-app to bootstrap the boilerplate code. Run the following command to create a new react app —
Using the onScroll
event-handler
The first thing that comes to mind is of-course, using the onScroll
event to implement infinite scrolling.
It’s simple to implement and easy to understand. Here is the code for it —
Let’s dissect it a little and understand what's going on inside the code —
- In the
utils.js
file we have defined two utility functions — first is to generate a randomrgb
color, and second function is to generatecellsCount
number of cells with a randomly generated background color. - Second we have defined a
OnScrollContainer
function component which have the randomly generated cells stored in aonScrollCells
state. - Then we have defined a
onScrollCellsUpdateDebounced
callback to be passed as theonScroll
event handler. Here we are using thedebounce
function fromlodash.debounce
library to optimize the number ofonClick
event-handler triggers. - The actual event-handler
onScrollCellsUpdate
is pretty straight-forward. We are executing asetTimeout
with500ms
when we scroll till bottom of the container.
Pretty easy, right!! Now let’s see if can do something better.
Using the IntersectionObserver
API
IntersectionObserver
is a newer web API available in most of the prominent browsers. IntersectionObserver
API solves the
classic problem of detecting visibility of an element on screen. Find more information about IntersectionObserver
(here)[https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API].
Let’s jump in the code —
Let’s dissect this too and understand what we are doing in code —
- The
utils.js
and storing the cells in state is same as theonScroll
example. Just the name of the cells’ state isioCells
. - Next we have created a custom react hook
useIOInfiniteScroll
which abstracts out the implementation ofIntersectionObserver
. This hook accepts two parameters, first is theref
to a loader-indicator element and second is the callback that needs to be executed when scrolled till bottom. - Now the idea here is to observe the loader-indicator element at the bottom of the scrollable container using
IntersectionObserver
. As soon as the loader-indicator element is visible on the screen,IntersectionObserver
will trigger the callback which we passed to it as the second parameter. This callback will have the logic to append more colored slabs to the container. - We should use the
IntersectionObserver
in auseEffect
hook. This will allow us to return a callback from theuseEffect
hook to unobserve the loading-element when the component unmounts.
That’s it!! But how is this approach better than the onScroll
approach? Let’s find out.
Final output combined
Both the onScroll
and IntersectionObserver
feels pretty much the same while using but there are some very fundamental
differences between both of these approaches and there are some reasons of why should one approach be favoured over the other.
Quick comparison
So here is my personal opinionated view of the differences between both of these approaches —
onScroll
- Since this is just another DOM event-handler, it’s easy to use and more intuitive as we are very much familiar with DOM events.
- Scroll event fires up a lot of times in even in just one small scroll, hence the event-handler might end up blocking the main thread.
In order to solve this problem we have to control the event-handler calls by using
debounce
, which is an extra effort. - We also have to keep in mind the event-bubbling/capturing phases too while implementing any event-handler, and so is the case with
scroll
event too.
IntersectionObserver
IntersectionObserver
is a newer API with wide support amongst all major browsers.IntersectionObserver
solves the problem of element visibility on screen in general, hence its applications spread beyond the use case of infinite-scrolling.IntersectionObserver
does not obliterate the main thread with a lot of callback executions on main thread unlikeonScroll
approach. It just executes the callback on main thread only when the observability conditions are met for a target element.- We also don’t need to go through the hassle of taking care of event bubbling/capturing phases and event debouncing/throttling when using
IntersectionObserver
.
So from this quick comparison above, it seems like IntersectionObserver
is generally the way forward now for not just infinite-scrolling but a lot more
other use-cases of element visibility on screen.