Introduction:
In the realm of web development, optimizing performance and efficiency is key to delivering exceptional user experiences. When dealing with large lists or tables, rendering every item in the DOM can lead to performance bottlenecks and increased memory usage. Thankfully, @tanstack/react-virtual comes to the rescue. You can check out the full docs here . In this article, we'll explore what @tanstack/react-virtual is, and guide you through using it step by step, empowering you to customize your virtualized components using React Hooks.
What is @tanstack/react-virtual?
@tanstack/react-virtual is a powerful library that enables efficient rendering of large datasets in React applications. By using virtualization techniques, it only renders the items currently visible on the screen, resulting in improved performance, reduced memory consumption, and a smoother user experience.
Step-by-Step Guide
Step 1: Installation
Begin by installing @tanstack/react-virtual as a dependency in your React project. You can use any package manager of your choice. However in this article we will go with yarn
yarn add @tanstack/react-virtual
Step 2: Importing the Library and React Hooks
After installing the library, import the necessary components and React Hooks into your project. In this example, we'll use the useVirtualizer
Hook provided by @tanstack/react-virtual. Import it alongside the required React modules as shown below:
import React, { useRef, useEffect } from 'react';
import { useVirtualizer } from '@tanstack/react-virtual';
Step 3: Setting up the Virtualized List
Create a functional component and define the necessary state variables.
function MyVirtualizedList() {
const parentRef = React.useRef<HTMLDivElement>(null)
const [listItems, setListItems] = useState<ListItem[]>([])
}
- The
parentRef
is used to reference the scrollable element for the list. - The
listItems
is an array of your list which you need to render.
Next, we will fetch out data from an api for the list items and update our state. This article assumes the fetching, so we will use the function getListItems()
for that. Our assumption is that the method returns an array of strings.
Please note the array can be of any type depending on what you need to render.
useEffect(()=>{
const data = getListItems();
setListItems(data)
}, [])
Next, we will create our virtualization using the hook we had imported earlier as below
const virtualizer = useVirtualizer({
count: listItems.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 35,
});
- The
count
property inuseVirtualizer
specifies the total number of items in the list. - The
getScrollElement
property is a callback function that returns the reference to the scrollable element. In this example, it is set to() => parentRef.current
to get the scrollable element from the parentRef useRef hook. - The
estimateSize
property provides an estimate of the row size in pixels. In this example, it is set to() => 35
.
Next, we will create our actual component to render the context of the virtualized items
function MyVirtualizedList() {
// Previous code goes here
const virtualItems = virtualizer.getVirtualItems();
const totalSize = virtualizer.getTotalSize();
return (
<>
<div ref={parentRef} className="overflow-auto h-400">
<div className="relative w-full" style={{ height: `${totalSize}px` }}>
{virtualItems.map(virtualItem => {
const listItem = listItems[virtualItem.index];
return (
<div
key={virtualItem.key}
className="absolute top-0 left-0 w-full"
style={{
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
Item: {listItem}
</div>
);
})}
</div>
</div>
</>
);
}
-
getVirtualItems()
method returns an array of virtual items currently visible in the viewport. You can iterate over this array to access and modify individual virtual items. -
getTotalSize()
method returns the total size in pixels for the virtualized items. This measurement will incrementally change if you choose to dynamically measure your elements as they are rendered.
While rendering we are mapping th virtualItems, then for each virtual items, we select an item from our listItems
depending on the array of that item. You can then render the item as to your preference and depending on the item structure. In our case the assumption was our list is an array of strings.
Step 4: Customizing the List with React Hooks
One of the advantages of using React Hooks is the flexibility to customize your virtualized list. You can modify the state variables, such as count
, or update the rendering logic based on your requirements. Additionally, you can incorporate other React Hooks, such as useState
or useEffect
, to manage additional state or handle side effects.
Step 5: Styling and UI Customization
To style your virtualized list, you can use any css library or write your own plain css. In this article however, we chose to use Tailwind CSS. Therefore you can ensure that Tailwind CSS is installed and configured in your project. Then, modify the JSX code to utilize Tailwind CSS classes to your taste:
Here is the full example
import React, { useRef, useEffect } from 'react';
import { useVirtualizer } from '@tanstack/react-virtual';
function MyVirtualizedList() {
const parentRef = React.useRef<HTMLDivElement>(null)
const [listItems, setListItems] = useState<ListItem[]>([])
useEffect(()=>{
const data = getListItems();
setListItems(data)
}, [])
const virtualizer = useVirtualizer({
count: listItems.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 35,
});
const virtualItems = virtualizer.getVirtualItems();
const totalSize = virtualizer.getTotalSize();
return (
<>
<div ref={parentRef} className="overflow-auto h-400">
<div className="relative w-full" style={{ height: `${totalSize}px` }}>
{virtualItems.map(virtualItem => {
const listItem = listItems[virtualItem.index];
return (
<div
key={virtualItem.key}
className="absolute top-0 left-0 w-full"
style={{
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
Item: {listItem}
</div>
);
})}
</div>
</div>
</>
);
}
Top comments (0)