【无标题】

Advisory boards aren’t only for executives. Join the LogRocket Content Advisory Board today →
LogRocket Blog

Rendering large lists in React: 5 methods with examples

July 14, 2022 6 min read

React Render Larg Lists

Editor’s note: This article was last updated on 14 July 2022 to replace tools that are no longer maintained.

Lists are an integral part of most web applications because they help display data in a more presentable format. But, when an app tries to handle too much data in a list, it often leads to performance problems.

In this guide, we’ll outline some problems associated with bloated lists, then walk through five different methods you can use to overcome these performance challenges in React applications.

To follow along with this tutorial, you’ll need the following:

A general understanding of JavaScript and React
npm ≥v5.2 or Yarn installed on your machine
Node.js ≥v12
Table of contents

Performance problems with large lists
Pagination
Infinite scroll
react-virtualized
react-window
React ViewPort List
Performance problems with large lists

Let’s create a sample application to demonstrate what happens to your app’s performance and the DOM tree when you try to render a large list of 10,000 records.

Launch your terminal and paste the code below to create a React application:

npx create-react-app render-list
Run the code below to install the Faker library, which we’ll use to generate random data to use in our application:

npm i @faker-js/faker
Next, go to the App component in the src directory and enter the code below:

import React from ‘react’;
import faker from ‘faker’
import ‘./App.css’;

const data = new Array(10000).fill().map((value, index) => ({ id: index, title: faker.lorem.words(5), body: faker.lorem.sentences(4) }))

function App() {
return (


{data.map(((item) => (

{item.title} - {item.id}


{item.body}



)))}

);
}
export default App;
Go the App.css file and add the lines of code below to add a little styling to the list:

.post{
background-color: #eee;
margin: 2rem;
padding: 1rem;
}
.pagination{
margin: 1rem auto;
list-style: none;
display: flex;
justify-content: space-evenly;
width: 50%;
}
.active{
border: 1px solid black;
border-radius: 100%;
padding: 0 3px;
outline: none;
}
The code above renders a list of 10,000 records. Start the React application in your browser and open your console:

Faker Example Rendered Lists Problems

When the page loads, there is a noticeable lag as you scroll. It’s not the large array of data that’s causing the lag, but the rendered DOM elements.

Large lists can be rendered both conditionally or dynamically. In React, conditional rendering refers to a concept of rendering components based on if certain conditions are met. There are various ways to use conditional rendering to render lists, like if or else statements, the ternary operator, and the logical && operator.

On the other hand, dynamic rendering renders components mainly by looping over an array of data using the map() method. Rendering large lists using either conditional or dynamic rendering has its pros and cons.

To better demonstrate, let’s cover five ways to solve list-related performance issues in React apps.

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 (


{pagination.currentData && pagination.currentData.map(((item, index) => (

{${item.title} - ${item.id}}


{item.body}



)))
}
<ReactPaginate
previousLabel={‘previous’}
nextLabel={‘next’}
breakLabel={‘…’}
pageCount={pagination.pageCount}
marginPagesDisplayed={2}
pageRangeDisplayed={5}
onPageChange={handlePageClick}
containerClassName={‘pagination’}
activeClassName={‘active’}
/>

);
}
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.

Over 200k developers use LogRocket to create better digital experiences

Learn more →
Below is a screenshot of how the app looks after pagination has been added to it:

Faker Example List Pagination

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-scroller. To install it, run the following code in your terminal:

npm i react-infinite-scroller
Open your App component and paste the following code:

import React, { useState } from ‘react’;
import faker from ‘faker’
import InfiniteScroll from “react-infinite-scroller”;
import ‘./App.css’;

function App() {
const data = new Array(1000).fill().map((value, index) => ({
id: index,
name: faker.name.firstName(5),
body: faker.lorem.paragraph(8),
}));
const showItems = (posts) => {
var items = [];
for (var i = 0; i < records; i++) {
items.push(


{${posts[i].name} - ${posts[i].id}}


{posts[i].body}



);
}
return items;
};
const itemsPerPage = 20;
const [hasMore, setHasMore] = useState(true);
const [records, setrecords] = useState(itemsPerPage);
const loadMore = () => {
if (records === data.length) {
setHasMore(false);
} else {
setTimeout(() => {
setrecords(records + itemsPerPage);
}, 2000);
}
};
return (
<InfiniteScroll
pageStart={0}
loadMore={loadMore}
hasMore={hasMore}
loader={
Loading…
}
useWindow={false}
>
{showItems(data)}

);
}
export default App;
Basically, 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 continues appending data to the end of the page until the hasMore property becomes false.

react-virtualized

react-virtualized was specifically designed for rendering large lists and tabular data. It uses a technique similar to infinite scroll called windowing that renders only the visible parts of a list to the screen.

One advantage react-virtualized has over the aforementioned solutions is its wealth of useful components, including Collection, Grid, List, Masonryf, and Table.

To install react-virtualized, launch your terminal and run the following code:

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 }) => (

{`${data[index].title}-${data[index].id}`}

{data[index].body}

) return ( ); } 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:

react-virtualized comes with several other options for handling large lists.

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 }) => (

{`${data[index].title}-${data[index].id}`}

{data[index].body}

) return ( {Row} ); } 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 at this GitHub repository.

React ViewPort List

Like react-virtualized, React ViewPort List utilizes a technique called windowing, which renders only a portion of the list at a time, significantly reducing the time it takes to re-render components as well as the number of DOM nodes created. React ViewPort List has some interesting features like:

Support for vertical and horizontal lists️️
Support for scroll to index
Flexbox alignment
Dynamic height and width for viewport
Install React ViewPort List by running the code below in your terminal:

npm i react-viewport-list
Go to your App component and replace the existing code with the code below:

import React from “react”;
import { faker } from “@faker-js/faker”;
import { useRef } from “react”;
import ViewportList from “react-viewport-list”;
const App = () => {
const ref = useRef(null);
const items = new Array(1000).fill().map((value, index) => ({
id: index,
name: faker.name.firstName(5),
body: faker.lorem.paragraph(8),
}));
return (



{(item) => (


{item.name} - {item.id}


{item.body}



)}


);
};
export default App;
The ViewportList component accepts an item prop that is assigned to a set of data for the lists. The list is then rendered as rows with a margin of 8px and a minimum height size of 40px.

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.

More great articles from LogRocket:

Don’t miss a moment with The Replay, a curated newsletter from LogRocket
Learn how LogRocket’s Galileo cuts through the noise to proactively resolve issues in your app
Use React’s useEffect to optimize your application’s performance
Switch between multiple versions of Node
Discover how to use the React children prop with TypeScript
Explore creating a custom mouse cursor with CSS
Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Get set up with LogRocket’s modern React error tracking in minutes:

Visit https://logrocket.com/signup/ to get an app ID.
Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
NPM
Script Tag
$ npm i --save logrocket

// Code:

import LogRocket from ‘logrocket’;
LogRocket.init(‘app/id’);
(Optional) Install plugins for deeper integrations with your stack:
Redux middleware
ngrx middleware
Vuex plugin
Get started now
Share this:
TwitterRedditLinkedInFacebook

Samaila Bala Follow
I’m a frontend engineer and technical writer.
#react
« Node.js buffer: A complete guide
Building a responsive login page in Flutter »

Stop guessing about your digital experience with LogRocket

Get started for free
The top tools for cleaning up your CSS

Frank Joseph
Aug 4, 2023 5 min read
Migrating Ruby projects to Go

Ukeje Goodness
Aug 3, 2023 6 min read
Best React Native search libraries

Nelson Michael
Aug 3, 2023 9 min read
3 Replies to “Rendering large lists in React: 5 methods with examples”

Qasim Says:
December 14, 2020 at 12:30 pm
Great article, the React-Pagination example here is better than the documentation. Thanks Ben!

Ravi Chaudhary Says:
February 7, 2022 at 2:12 pm
Nice article. Just one question – In Infinite scroll approach, more items will keep on appending to the list until all the the items are downloaded. Wouldn’t it make the DOM heavy eventually thereby causing the performance issues again?

Zaakir Mungrue Says:
March 4, 2022 at 12:52 am
Excellent Article here. The pagination example was not useful I had to build my own component from scratch. In reply to the. above comment, the items of the list are only rendered when they appear on the window because of scrolling the list. react-window must estimate the number of rows that can fit into the height of the screen and only that number of items are rendered

Leave a Reply

Does something seem off? Email support@logrocket.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值