React Virtualization: Efficiently Handling Large Lists and Grids

Harry Bloch
4 min readMay 13, 2023

React is a powerful JavaScript library, often lauded for its flexibility and efficiency. However, when it comes to dealing with large lists and grids, even React can start to buckle under the weight. In this post, we’ll explore the concept of React Virtualization, a technique that can help us render large lists and grids in a more efficient manner. Additionally, we’ll delve into how to fetch large lists from a Firebase Real-time Database.

But before we get started, if you enjoy this post and would like to read more of my insights on programming and technology, I invite you to follow me on Medium and Twitter for regular updates.

What is React Virtualization?

React Virtualization is a technique used to optimize the rendering of large lists and grids in React applications. The idea is to only render the items that are currently visible in the user’s viewport, thereby reducing the number of DOM nodes that React needs to manage.

The basic concept of virtualization is windowing. Instead of rendering the entire list or grid, React virtualization creates a ‘window’ of visible content and renders only the components within this window. As the user scrolls, the window moves, and React intelligently unmounts the components that have scrolled out of view and mounts the ones that have scrolled into view.

Refactoring for Better Performance

Let’s consider a common example of non-optimized code, where we are trying to render a large list of users fetched from a Firebase database.

import React from 'react';
import { db } from './firebase';

class UserList extends React.Component {
state = { users: [] };

componentDidMount() {
db.ref('users').on('value', snapshot => {
let users = [];
snapshot.forEach(snap => {
users.push(snap.val());
});
this.setState({ users: users });
});
}

render() {
return (
<div>
{this.state.users.map((user, index) => (
<div key={index}>{user.name}</div>
))}
</div>
);
}
}

export default UserList;

While this code works fine for a small list of users, it will start to slow down as the list grows. To refactor this, we can leverage React Virtualization using the react-window library.

import React from 'react';
import { db } from './firebase';
import { FixedSizeList as List } from 'react-window';

class UserList extends React.Component {
state = { users: [] };

componentDidMount() {
db.ref('users').on('value', snapshot => {
let users = [];
snapshot.forEach(snap => {
users.push(snap.val());
});
this.setState({ users: users });
});
}

Row = ({ index, style }) => (
<div style={style}>{this.state.users[index].name}</div>
);

render() {
return (
<List
height={500}
itemCount={this.state.users.length}
itemSize={35}
width={300}
>
{this.Row}
</List>
);
}
}

export default UserList;

Retrieving Large Lists from Firebase Real-time Database

Fetching large datasets in real-time can also present performance issues. One way to manage this is by paginating data from Firebase.

This involves setting a limit to the number of records fetched at a time and then fetching more records as required. To fetch data from Firebase in pages, you can use the limitToFirst or limitToLast methods combined with startAt, endAt, or equalTo.

componentDidMount() {
let ref = db.ref('users').orderByKey();

ref.limitToFirst(50).once('value', snapshot => {
let users = [];
snapshot.forEach(snap => {
users.push(snap.val());
});
this.setState({ users: users });
});
}

In this code, we’re using orderByKey() to order our records and limitToFirst(50) to fetch the first 50 records.

As users scroll, we can then fetch the next set of data.

loadMoreUsers() {
let lastKey = this.state.users[this.state.users.length - 1].key;
let ref = db.ref('users').orderByKey().startAt(lastKey);

ref.limitToFirst(50).once('value', snapshot => {
let users = [...this.state.users];
let newUsers = [];
snapshot.forEach(snap => {
newUsers.push(snap.val());
});
// Remove first user because it's duplicate
newUsers.shift();

this.setState({ users: [...users, ...newUsers] });
});
}

In loadMoreUsers(), we fetch the next 50 records starting from the last key in our current users list.

Remember, this is a basic implementation and you might need to add more features like a loading indicator or error handling based on your specific needs.

Conclusion

React virtualization is an indispensable tool when it comes to dealing with large lists and grids in React. Not only does it improve the performance of your application, but it also enhances the user experience by providing faster, smoother scrolling.

Remember, the secret to handling large data sets in React is not just about optimizing what is visible to the user, but also efficiently managing what goes on behind the scenes.

If you found this post helpful and want to learn more about React or other topics in technology, follow me on Medium and Twitter for more insights, tips, and tutorials. Your support means a lot and it helps me to keep producing content like this.

In the end, the journey of becoming a better developer is about continuous learning and improvement, and I’m here to support you on this journey. Happy coding!

--

--