React Window - Optimized way to display large list

In Web development, there will be always a need to display content in a large list. Renderering a large list will slow down the web page load and increase the First Contentful Paint(FCP). Usually large lists are displayed in a paginated grid where user has to move around pages by clicking next. It will be good user experience, if the same page provides data of large list as and when we scroll.
Web users can see few items in the list at any point of time based on the screen view. Virtualize the list to show the items to be visible for the users and on scroll pre-render the list items, so it gives the users impression of rendering the large list. This is the idea of react-window component developed by Brain Vaughn, core team member of React JS team.
Introduction:
React Window is a react component licensed under MIT license for rendering virtualized view of large list. It address below performance bottlenecks:
1. It reduces the amount of work (and time) required to render the initial view and to process updates.
2. It reduces the memory footprint by avoiding over-allocation of DOM nodes.
List virtualization concept focus on rendering items visible to user. It then maintains the windows moving around the list. This concept adapted from the video game of virtualized view as view moves in.
Implementation:
In this blog, we will show huge list of zip codes of particular state and on click of it shows weather data dynamically using weather forecast api. As there are more than 45K zip codes of California state, rendering the huge list will burden the UI rendering of it. Using react window, lets do the virtualized view of the zip codes.
FixedSizeList Component:
FixedSizeList react component which we need to give the list items length which is comprised of the row item component to show the row content. Important parameters are itemCount which is the total count of the list and itemSize is the list of the items pre-rendered for the virtualized view.
<FixedSizeList
height={450}
width={"100%"}
itemSize={50}
itemCount={items.length}
style={{ backgroundColor: "#e4ebe8" }}
columnWidth={COLUMN_WIDTH + GUTTER_SIZE}
rowHeight={ROW_HEIGHT + GUTTER_SIZE}
>
{Row1}
</FixedSizeList>
Row1 is the internal react component which show the list item with zip code and place name shown as item. Data item component receives the index and style parameter. As we are having the items as component level model, items will be referred directly i.e items.
const Row1 = ({ index, style }) => (
<>
<div
style={{
...style,
alignItems: "center",
display: "flex",
justifyContent: "center",
left: style.left + GUTTER_SIZE,
top: style.top + GUTTER_SIZE,
height: style.height - GUTTER_SIZE,
}}
onClick={() => {
console.log(items.length);
console.log("index", items[index][0]);
setValue(items[index][0]);
}}
>
<p>
{items[index][1]} - {items[index][0]}
</p>
</div>
</>
);
This virutalized view works based on the height of the list, so we can add the height with left and top padding using common gutter size value to the style property argument. For zipcode data, refer the files in the location.
When we click on the left zip code item, it will invoke the free weather api( http://api.weatherapi.com/v1/current.json?key=${key}&q=${value}&aqi=no ) to get the detailed weather report of that particular location. The weather information will be displayed in the right part of the screen. React Window allow to hook click events on the rendered list items. It comes as shown below having the list item and right side showing the weather of the clicked item.
Now if we inspect the items and check DOM structure inside the list, we could see almost 12 to 13 items. Scroll the items in the left list, DOM list items changes accordingly as we scroll the items. Please refer the below gif on clarifying this.
This works well for the fixed size list items. As of now we cannot implement variable size list item or not able to achieve this as far as we know it. Whole project is availble in the github for reference.
Below video will help in visualizing the project.
Complete source of this project is available in Github.