Sitemap
Better Programming

Advice for programmers.

How I Rendered a Massive List in React Without Memory and CPU Issues

4 min readOct 28, 2019

--

The Massive List

I was in a situation where I had to render a large number of items in a list. I was desperate because of the issues I was facing in React whenever I wanted to render a huge list or a table.

Based on what I’m planning to render as a list item and the length of the list, I was facing these issues:

  1. Taking too much time to render the list (CPU issue)
  2. There’s a huge lag while scrolling (memory issue)
  3. The entire app became slow

Things I Tried That Didn’t Work

I realized it’s not the large array of elements that’s causing the lag but the rendered DOM elements.

So I thought I’d split the array into multiple chunks and render the one chunk first. Whenever the user hit the bottom of the list, I’d render the next one.

But this didn’t work out so well. The user experience wasn’t good. When you hit the bottom, I’d still be rendering the next chunk, and there was a lag in between. Even though it was killing the UX, I fixed it with some hacks. But the actual problem was this: Whenever I added a chunk, the render-list size was increasing, and the user would end up facing the same lag issue while scrolling.

My second attempt: Whenever I added one chunk, I’d remove the previous one. Was that it? Yeah, it worked to extend and solved the memory issue, but it killed the UX. Whenever I scrolled, the scrollbar was moving up and down, and because of the positioning of items getting changed when I’d remove the previous chunk, I felt like items were disappearing that were supposed to be present in the list.

How I Finally Solved It

Lessons from the previous attempts were when a user scrolls the positioning of an element should never change, and rendering only what’s visible on the view can solve the CPU and memory issues.

Well, my only option was to split the array to different chunks and put a container for each chunk instead of rendering the items directly. It’d be necessary to maintain the height of each container when I removed items inside the container while it’s not in the view.

The question was based on the splitting the array and the size of each chunk. Size matters because if there are 10,000 elements in the array and if my chunk size is 10, then I’ll be rendering 1,000 container divs.

This is when I thought, “Why can’t I implement the binary tree here?” I recursively split the array in half until each chunk had a minimum number of elements. This way, if the parent container isn’t visible in the view, then all of its children container will automatically get removed while maintaining the position of each element.

The Implementation in React

Once I got the logic, implementing it was pretty simple. I’m not going to explain all the code here because that’d be too verbose. Instead I’ll simply walk you through the flow.

Let’s consider your list as a component. When the list of data is provided to the list, the data will be going through these processes.

  1. We’ll be taking the list data and splitting it recursively until one chunk reaches a minimum of items, and then we’ll store it.
  2. Visibility checking: In the processed data, we’ll be updating the visibility of each container based on the scrollTop of the list component by looping recursively. I could’ve done it in the first step only, but the reason why I wanted to separate it is this function will be getting called whenever there is a scroll event triggered.
  3. We’ll be binding the visibility-checking function to the onScroll of the list component.

That’s all. Now, we have the list, which is capable of rendering a large number of list items without memory and CPU issues.

The Working Demo and NPM Library

I thought it didn’t make sense to make others write the same code I’ve already written, so I made an NPM library and hosted a working demo.

Working Demo

NPM Library: React-Eternal-List

Conclusion

The binary-tree approach worked out really well. I’ve tried up to 100,000 elements, and it was still working smoothly. Even though I spent some time achieving this, it was worth the effort. Even if it was just a list, the learning curve was good, and now I can use this approach in my future UI development.

Thanks for your interest. Do you have a different opinion? I’m always glad to get feedback.

--

--