1. Pagination
Pagination allows you to render data in pages as opposed to rendering all the information at once. This way, you basically control the amount of data that is shown on the page, so you don’t have to put too much stress on the DOM tree.
Most UI libraries in React come with a pagination component, but if you want to quickly implement pagination without having to install a UI library, you might want to check out react-paginate
. The library renders a pagination component that accepts some props helps you navigate through your data.
To install the library, run the code below in your terminal.
npm i react-paginate
After installation, you can modify your App
component to paginate the data instead of rendering it at once. Paste the code below in your App
component.
import React, { useState, useEffect } from 'react'; import ReactPaginate from 'react-paginate'; import faker from 'faker' import './App.css'; function App() { const [pagination, setPagination] = useState({ data: new Array(1000).fill().map((value, index) => (({ id: index, title: faker.lorem.words(5), body: faker.lorem.sentences(8) }))), offset: 0, numberPerPage: 10, pageCount: 0, currentData: [] }); useEffect(() => { setPagination((prevState) => ({ ...prevState, pageCount: prevState.data.length / prevState.numberPerPage, currentData: prevState.data.slice(pagination.offset, pagination.offset + pagination.numberPerPage) })) }, [pagination.numberPerPage, pagination.offset]) const handlePageClick = event => { const selected = event.selected; const offset = selected * pagination.numberPerPage setPagination({ ...pagination, offset }) } return ( <div> {pagination.currentData && pagination.currentData.map(((item, index) => ( <div key={item.id} className="post"> <h3>{`${item.title} - ${item.id}`}</h3> <p>{item.body}</p> </div> ))) } <ReactPaginate previousLabel={'previous'} nextLabel={'next'} breakLabel={'...'} pageCount={pagination.pageCount} marginPagesDisplayed={2} pageRangeDisplayed={5} onPageChange={handlePageClick} containerClassName={'pagination'} activeClassName={'active'} /> </div> ); } export default App;
In this example, we’re storing the details responsible for the pagination in our paginating state. Instead of rendering the data at once, we only render the current data, which we get by slicing the main data based on the current offset and the number of records to be displayed on the page.
The ReactPaginate
component accepts an event handler as a prop, which is called whenever the page changes. The event handler calculates the current offset, which is then used to calculate the current data to display when the page loads.
Below is a screenshot of how the app looks after pagination has been added to it.

2. Infinite scroll
Another way to render a large amount of data is with infinite scroll. Infinite scroll involves appending data to the end of the page as you scroll down the list. When the page initially loads, only a subset of data is loaded. As you scroll down the page, more data is appended.
There are several ways to implement infinite scroll in React. Personally, I prefer to use react-infinite-scroll-component
. To install it, run the following code in your terminal.
npm i react-infinite-scroll-component
Open your App
component and paste the following.
import React, { useState } from 'react'; import faker from 'faker' import InfiniteScroll from 'react-infinite-scroll-component'; import './App.css'; function App() { const data = new Array(1000).fill().map((value, id) => (({ id: id, title: faker.lorem.words(5), body: faker.lorem.sentences(8) }))) const [count, setCount] = useState({ prev: 0, next: 10 }) const [hasMore, setHasMore] = useState(true); const [current, setCurrent] = useState(data.slice(count.prev, count.next)) const getMoreData = () => { if (current.length === data.length) { setHasMore(false); return; } setTimeout(() => { setCurrent(current.concat(data.slice(count.prev + 10, count.next + 10))) }, 2000) setCount((prevState) => ({ prev: prevState.prev + 10, next: prevState.next + 10 })) } return ( <InfiniteScroll dataLength={current.length} next={getMoreData} hasMore={hasMore} loader={<h4>Loading...</h4>} > <div> {current && current.map(((item, index) => ( <div key={index} className="post"> <h3>{`${item.title}-${item.id}`}</h3> <p>{item.body}</p> </div> ))) } </div> </InfiniteScroll> ); } export default App;
Basically what happens here is whenever the user scrolls to the end of the page it checks if the hasMore
property is false. If it isn’t it appends more data to the page. It keeps on appending data to the end of the page until the hasMore
property becomes false.
3. react-virtualized
react-virtualized
was specifically designed for rendering large lists and tabular data. It uses a technique similar to infinite scroll called windowing. With windowing, only the visible parts of a list are rendered to the screen.
One advantage react-virtualized
has over the aforementioned solutions is its wealth of useful components, including:
Collection
Grid
List
Masonryf
Table
To install react-virtualized
, launch your terminal and run the following.
npm i react-virtualized
Go to your App
component and paste the code below.
import React from 'react'; import faker from 'faker' import { List } from "react-virtualized"; import './App.css'; function App() { const data = new Array(1000).fill().map((value, id) => (({ id: id, title: faker.lorem.words(5), body: faker.lorem.sentences(8) }))) const renderRow = ({ index, key, style }) => ( <div> <div key={key} style={style} className="post"> <h3>{`${data[index].title}-${data[index].id}`}</h3> <p>{data[index].body}</p> </div> </div> ) return ( <List width={1200} height={700} rowRenderer={renderRow} rowCount={data.length} rowHeight={120} /> ); } export default App;
The List
component takes the width
and height
props to set the dimensions of the window. It also takes the rowHeight
prop, which represents the height of every item in the list, and rowCount
, which represents the length of the array. rowRenderer
takes a function that is responsible for rendering each row.
4. react-window
react-window
is a set of components for efficiently rendering large lists in React. A complete rewrite of react-virtualized
, the library aims to address shortcomings related to size and speed. react-window
also covers more edge cases than react-virtualized
.
Install react-window
by running the code below in your terminal.
npm i react-window
Go to your App
component and replace the code with the code below.
import React from 'react'; import faker from 'faker' import { FixedSizeList as List } from "react-window"; import './App.css'; function App() { const data = new Array(1000).fill().map((value, id) => (({ id: id, title: faker.lorem.words(5), body: faker.lorem.sentences(8) }))) const Row = ({ index, key, style }) => ( <div> <div key={key} style={style} className="post"> <h3>{`${data[index].title}-${data[index].id}`}</h3> <p>{data[index].body}</p> </div> </div> ) return ( <List width={1400} height={700} itemCount={data.length} itemSize={120} > {Row} </List> ); } export default App;
The code is very similar to that of react-virtualized
. We used a List
component, which accepts a set of props that defines the list, and passed in a Row
component function, which is responsible for rendering each row in the list.
The author of the library outlined the differences between react-window
and react-virtualized
.
Conclusion
When handling a large list, it’s important not to render all the data at once to avoid overloading the DOM tree. The best approach to improving performance depends on your use case. If you prefer to render all the data in one place, infinite scroll or a windowing technique would be your best bet. Otherwise, you may prefer a pagination solution that segments data into different pages.