Reverse Infinite Scrolling in React | Chat app like scrolling
— React, Web Development — 3 min read
In this tutorial, we'll learn how to implement Reverse Infinite Scrolling, similar to a Chat-app, in React using a third-party library called "react-infinite-scroll-component".
You can download or clone the completed code for this tutorial from this github repo. In your terminal, cd
into the tutorial directory and run npm i
followed by npm run dev
which should start a localhost web server. If you visit the localhost URL, you'll see this output.
Lets look at the code to understand how to implement this. Open /src/App.jsx
in your code editor.
import { useState } from "react";import InfiniteScroll from "react-infinite-scroll-component";
export default function App() { const [ data, setData ] = useState( [1,2,3,4,5,6,7,8,9,10] ); const MAX_DATA = 30; const hasMore = data.length < MAX_DATA;
function fetchData( limit=10 ){ const start = data.length + 1; const end = (data.length + limit) >= MAX_DATA ? MAX_DATA : (data.length + limit); let newData = [ ...data ]; for( var i = start ; i <= end ; i++ ) { newData = [ ...newData, i ]; } // fake delay to simulate a time-consuming network request setTimeout( () => setData( newData ), 1500 ); }
return ( <div id="scrollableDiv" style={{width: "500px", height: "100vh", overflowY: "scroll", display: "flex", flexDirection: "column-reverse", margin: "auto"}} className="bg-body-tertiary p-3"> <InfiniteScroll dataLength={ data.length } next={fetchData} hasMore={hasMore} loader={<p className="text-center m-5">⏳ Loading...</p>} endMessage={<p className="text-center m-5">That's all folks!🐰🥕</p>} style={{ display: "flex", flexDirection: "column-reverse", overflow: "visible" }} scrollableTarget="scrollableDiv" inverse={true} > { data.map( d => ( <div className="card mb-4" key={d} style={{width: "18rem"}}> <div className="card-header">Card#{d}</div> <div className="card-body">Lorem ipsum dolor sit amet</div> </div> )) } </InfiniteScroll> </div> )}
I have already explained how normal Infinite scrolling can be implemented using this library in my previous blog post where I have also explained the purpose of most of the attributes of the <InfiniteScroll />
component used above.
The attributes that are specific to the reverse scroll scenario are inverse
and scrollableTarget
.
The inverse
attribute should be set to true
to make sure the items appear in the reverse sequence.
The scrollableTarget
attribute takes the ID of an element as its value. By default, the scrollable target is the document or the <body />
. With the scrollableTarget
attribute, we can specify a custom DOM element as the container for housing the infinite scroll behaviour. In our tutorial, the div with ID scrollableDiv
is the value of the scrollableTarget
attribute. If you notice in the browser output, the main scroll bar to the right of the browser is missing and instead the scroll happens on scrollableDiv
.
Now the other aspect of making scrolling work in reverse is the CSS part.
You'll notice we have CSS styles defined for the <InfiniteScroll />
component and on #scrollableDiv
. These CSS styles are required for the reverse behaviour to work properly.
Assuming, your data in data
is a list of entries in descending order ( of creation ), normally you'd have the latest created item on top. But with flex-direction: column-reverse
on the <InfiniteScroll />
component, this sequence is reversed so that the latest created item appears last. And the same flex-direction: column-reverse
styling is also applied to #scrollableDiv
so that the scroll bar sticks to the bottom of the list rather than to the top.
You can of course customize the width of the #scrollableDiv
and choose to not have everything centered by removing margin:auto
but the rest of the styles should remain as is.
The classes are bootstrap specific and you can remove them with your classes or inline styles to achieve a similar CSS effect.
And that's it! With "react-infinite-scroll-component", it becomes pretty simple and straight-forward to implement Chat-app like scrolling behaviour quickly.
Hope this helps!🙏