Contact Support
Scrolling in React ListView component
23 Jan 202514 minutes to read
Scrolling is a technique that allows you to load more items as the user scrolls through a list, providing a seamless and dynamic user experience. This document explains how to implement scrolling in the React ListView component.
To implement scrolling, render the ListView with a dataSource
and bind the scroll event. Within the scroll event handler, you can access information such as the scroll direction, event name, and the distance from the scrollbar to the top and bottom ends through the distanceY parameter.
In the following example, new data is dynamically added while scrolling. When the user scrolls to the bottom and the remaining scrollable distance is less than 100 pixels, it loads a new batch of items into the list. This process continues as long as there are more items to render, providing a smooth, infinite scrolling experience.
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
import './index.css';
function App() {
let listviewInstance = null;
let data = [{
text: "Hi Guys, Good morning! \uD83D\uDE0A, I'm very delighted to share with you the news that our team is going to launch a new mobile application",
positionClass: 'right',
}, {
text: "Oh! That's great \uD83D\uDE42",
positionClass: 'left',
},
{
text: 'That is a good news \uD83D\uDE00',
templateHeight: '80px',
positionClass: 'right',
},
{
text: 'What kind of application we are gonna launch? \uD83E\uDD14',
positionClass: 'left',
},
{
text: 'A kind of "Emergency Broadcast App" like being able to just invite someone to teams without it impacting how many people have official access',
positionClass: 'right',
},
{
text: 'Who will be the client users for our applications? ',
positionClass: 'left',
},
{
text: 'Is currently the only way to invite someone through 0365? Just wondering down the road how organization would want to handle that with freelancers, like being able to just invite someone to teams without it impacting how many people have official access \uD83D\uDE14',
positionClass: 'right',
},
{
text: 'Yes, however, that feature of inviting someone from outside your organization is planned - expected closer to GA next year \uD83D\uDC4D',
positionClass: 'left',
},
{
text: 'I guess we should switch things over to hear for a while. How long does the trial last? \uD83E\uDD14',
positionClass: 'right',
},
{ text: 'I think the trial is 30 days. \uD83D\uDE03', positionClass: 'left' },
{
text: 'Only 0365 only members of your organization. They said that they are listening to customer feedback and hinted that guest users would be brought in down the road \uD83D\uDE09',
positionClass: 'right',
},
{ text: 'Cool thanks! \uD83D\uDC4C', positionClass: 'left' }
];
function listTemplate(data) {
const wrapperClass = `e-list-wrapper e-list-multi-line${data.positionClass === 'right' ? ' e-list-wrapper-right' : ''}`;
return (
<div className={wrapperClass}>
<span className="e-list-item-header text-span">
{data.text}
</span>
</div>
);
}
let itemsRendered = 5;
let itemPerScroll = 5;
let result = [];
const onListScrolled = (args) => {
if (args.scrollDirection === 'Bottom' && args.distanceY < 100) {
if (itemsRendered < data.length) {
const startIndex = itemsRendered;
const endIndex = Math.min(itemsRendered + itemPerScroll, data.length);
result = data.slice(startIndex, endIndex);
listviewInstance.addItem(result);
itemsRendered = endIndex;
}
}
}
return (
<div className="grid-container"><div><h3>Chat</h3>
<ListViewComponent id='list' dataSource={data.slice(0, itemsRendered)} height="320px"
width="400px" template={listTemplate.bind(this)} cssClass='e-list-template' scroll={onListScrolled.bind(this)} ref={scope => { listviewInstance = scope; }}></ListViewComponent>
</div></div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
function App(this: any) {
let listviewInstance: ListViewComponent | null = null;
let data: { text: string; positionClass: string; templateHeight?: string }[] = [{
text: "Hi Guys, Good morning! \uD83D\uDE0A, I'm very delighted to share with you the news that our team is going to launch a new mobile application",
positionClass: 'right',
}, {
text: "Oh! That's great \uD83D\uDE42",
positionClass: 'left',
},
{
text: 'That is a good news \uD83D\uDE00',
templateHeight: '80px',
positionClass: 'right',
},
{
text: 'What kind of application we are gonna launch? \uD83E\uDD14',
positionClass: 'left',
},
{
text: 'A kind of "Emergency Broadcast App" like being able to just invite someone to teams without it impacting how many people have official access',
positionClass: 'right',
},
{
text: 'Who will be the client users for our applications? ',
positionClass: 'left',
},
{
text: 'Is currently the only way to invite someone through 0365? Just wondering down the road how organization would want to handle that with freelancers, like being able to just invite someone to teams without it impacting how many people have official access \uD83D\uDE14',
positionClass: 'right',
},
{
text: 'Yes, however, that feature of inviting someone from outside your organization is planned - expected closer to GA next year \uD83D\uDC4D',
positionClass: 'left',
},
{
text: 'I guess we should switch things over to hear for a while. How long does the trial last? \uD83E\uDD14',
positionClass: 'right',
},
{ text: 'I think the trial is 30 days. \uD83D\uDE03', positionClass: 'left' },
{
text: 'Only 0365 only members of your organization. They said that they are listening to customer feedback and hinted that guest users would be brought in down the road \uD83D\uDE09',
positionClass: 'right',
},
{ text: 'Cool thanks! \uD83D\uDC4C', positionClass: 'left' }
];
function listTemplate(data: any): JSX.Element {
const wrapperClass = `e-list-wrapper e-list-multi-line${data.positionClass === 'right' ? ' e-list-wrapper-right' : ''}`;
return (
<div className={wrapperClass}>
<span className="e-list-item-header text-span">
{data.text}
</span>
</div>
);
}
let itemsRendered = 5;
let itemPerScroll = 5;
let result: { text: string; positionClass: string; templateHeight?: string }[] = [];
const onListScrolled = (args: any) => {
if (args.scrollDirection === 'Bottom' && args.distanceY < 100) {
if (itemsRendered < data.length) {
const startIndex = itemsRendered;
const endIndex = Math.min(itemsRendered + itemPerScroll, data.length);
result = data.slice(startIndex, endIndex) as { text: string; positionClass: string; templateHeight?: string }[];
listviewInstance.addItem(result);
itemsRendered = endIndex;
}
}
}
return (
<div className="grid-container"><div><h3>Chat</h3>
<ListViewComponent id='list' dataSource={data.slice(0, itemsRendered)} height="320px"
width="400px" template={listTemplate as any} cssClass='e-list-template' scroll={onListScrolled as any} ref={scope => { listviewInstance = scope; }}></ListViewComponent>
</div></div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));
#container {
visibility: hidden;
}
#loader {
color: #008cff;
height: 40px;
width: 30%;
position: absolute;
font-family: 'Helvetica Neue', 'calibiri';
font-size: 14px;
top: 45%;
left: 45%;
}
#element,
#list {
display: block;
margin: auto;
border-radius: 3px;
}
#element {
max-width: 280px;
}
#list {
max-width: 400px;
border: 1px solid #dddddd;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
align-items: center;
}
.grid-container>div {
border: 1px solid #ddd;
padding: 20px;
border-radius: 5px;
background-color: #f4f4f4;
}
h3 {
margin: 0;
}
.e-list-wrapper-right {
display: flex;
justify-content: flex-end;
}
.text-span {
white-space: normal !important;
max-width: 80%;
padding: 10px !important;
background-color: #e0e0e0;
border-radius: 10px;
word-wrap: break-word;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React ListView</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-react-lists/styles/material.css" rel="stylesheet" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='element' style="margin:0 auto; max-width:400px;">
<div id='loader'>Loading....</div>
</div>
</body>
</html>