?? Supercharged Virtualized List in React (No Boring Libraries!)
?? Supercharged Virtualized List in React (No Boring Libraries!) ??
Rendering long lists in React can be SLOW ??—but don’t worry! Today, we’ll build a Virtualized List without any libraries, making it fast, smooth, and lightweight! ??
What is Virtualization? ??
Virtualization is like a magician’s trick ??—instead of rendering ALL items at once (which is a bad idea ????), we only render what’s visible. This keeps things buttery smooth ??.
How Virtualized Lists Work (with a Chart ??)
Here’s how normal lists vs virtualized lists behave:
Type Rendering Method Performance ?? Traditional List Renders everything ?? Slow! ?? Virtualized List Renders only visible items ?? Fast! ?
?? Visualizing Virtualization
|----------------------------------|
| Viewport (User sees these) |
| ----------------------------- |
| ? Item 1 |
| ? Item 2 |
| ? Item 3 |
| ? Item 4 |
| ----------------------------- |
| ?? (Hidden Items) |
|----------------------------------|
Now let’s code it! ??
Step 1: Build the Virtualized List ??
Create VirtualizedList.jsx inside src/components/ and add:
import { useState, useEffect, useRef } from "react";
const generateItems = (count) => Array.from({ length: count }, (_, i) => `Item ${i + 1}`);
const VirtualizedList = () => {
const [items] = useState(generateItems(10000)); // ?? Magic: Large dataset
const [visibleItems, setVisibleItems] = useState([]);
const listRef = useRef(null);
const itemHeight = 40;
const viewportHeight = 400;
useEffect(() => {
const handleScroll = () => {
if (!listRef.current) return;
const scrollTop = listRef.current.scrollTop;
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = startIndex + Math.ceil(viewportHeight / itemHeight);
setVisibleItems(items.slice(startIndex, endIndex));
};
handleScroll();
listRef.current.addEventListener("scroll", handleScroll);
return () => listRef?.current?.removeEventListener("scroll", handleScroll);
}, [items]);
const handleClick = (event) => {
const itemId = event.target.getAttribute("data-id");
if (itemId) {
alert(`You clicked on Item ${itemId}`);
}
};
return (
<div
ref={listRef}
onClick={handleClick}
style={{ width: "300px", height: `${viewportHeight}px`, overflowY: "auto", border: "1px solid black", position: "relative" }}
>
<div style={{ height: `${items.length * itemHeight}px`, position: "relative" }}>
{visibleItems.map((item, index) => (
<div
key={index}
data-id={items.indexOf(item) + 1}
style={{ position: "absolute", top: `${items.indexOf(item) * itemHeight}px`, left: 0, right: 0, height: `${itemHeight}px`, padding: "10px", borderBottom: "1px solid #ddd", backgroundColor: "white", cursor: "pointer" }}
>
{item}
</div>
))}
</div>
</div>
);
};
export default VirtualizedList;
领英推荐
Step 3: Use It in App.jsx ??
Modify src/App.jsx to use the virtualized list:
import VirtualizedList from "./components/VirtualizedList";
function App() {
return (
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh" }}>
<VirtualizedList />
</div>
);
}
export default App;
Step 4: Run Your Blazing-Fast App ??
npm run dev
?? Why This is the Best Approach?
? Uses only useState, useEffect, and useRef—NO bloated dependencies! ???? ? Renders only visible items, making it super fast and efficient ???. ? Handles 10,000+ items smoothly without any lag ???. ? Perfect for long lists in dashboards, chats, logs, etc. ??.
What if You Want Click Events on Items? ??
If you want to handle clicks using the parent element instead of each individual item, simply add an onClick event to the parent div and use event.target.getAttribute("data-id") to detect which item was clicked:
const handleClick = (event) => {
const itemId = event.target.getAttribute("data-id");
if (itemId) {
alert(`You clicked on Item ${itemId}`);
}
};
This approach ensures better performance by reducing event listeners on each child element! ??
Final Thoughts ??
With this approach, your app will be as fast as The Flash ?! Want to take it further? Try adding lazy image loading or infinite scrolling for even cooler effects! ??
Let me know if you want an infinite scrolling tutorial next! ????