DEV Community

Cover image for Virtualize API call for loading Large Data in React-Select with React-Window
Dip Chowdhury
Dip Chowdhury

Posted on

Virtualize API call for loading Large Data in React-Select with React-Window

Hello internet folks! I’m pretty new to writing and sharing stuff on the internet, but I believe that by sharing our knowledge, we can build new cybernetic pyramids full of computational power! 🧑🏾‍💻🧑🏾‍💻🧑🏾‍💻

A few days ago, I was loading some data for my current clients at “CDP” where I was trying to show 1000+ data. Everything was going well until we received a requirement to scrape and find 75000+ entries and display them using React-Select, which was previously handling the 1000+ data.

Given my experience in this field, as soon as I heard the news, I knew that React wouldn’t be ideal for creating 75000+ list components to select from, especially when each of them might have their own CSS and listeners.

So what can we do? In the React-select Advance section, you might find a solution where you listen to keystrokes or the end of scrolling to bring in new data. However, I was thinking of pulling all the data back into my client and then processing it virtually using some other technique.

I came across some ideas on Stack Overflow that might help you. In another post, I may explain it in more detail, but for now, you can have a look at this code. It will help you with your problem.

Happy coding, and see you in the next post! 🕸🕸🕸

`import React, { useState, useCallback, useEffect, useRef } from "react"; import { FixedSizeList as List } from "react-window"; import InfiniteLoader from "react-window-infinite-loader"; const LOADING = 1; const LOADED = 2; const CustomMenuList = ({ children, initialOffset }) => { const itemHeight = 50; const [itemStatusMap, setItemStatusMap] = useState({}); const itemStatusMapRef = useRef(itemStatusMap); useEffect(() => { itemStatusMapRef.current = itemStatusMap; }, [itemStatusMap]); const isItemLoaded = useCallback((index) => !!itemStatusMapRef.current[index], []); const loadMoreItems = useCallback((startIndex, stopIndex) => { setItemStatusMap((prevStatusMap) => { const newStatusMap = { ...prevStatusMap }; for (let index = startIndex; index <= stopIndex; index++) { newStatusMap[index] = LOADING; } return newStatusMap; }); return new Promise((resolve) => { setTimeout(() => { setItemStatusMap((prevStatusMap) => { const newStatusMap = { ...prevStatusMap }; for (let index = startIndex; index <= stopIndex; index++) { newStatusMap[index] = LOADED; } return newStatusMap; }); resolve(); }, 2500); }); }, []); const Row = React.memo(({ index, style }) => { let label; if (itemStatusMap[index] === LOADED) { label = children[index]; } return ( <div style={{ ...style }}> {label || "Loading..."} </div> ); }); return ( <InfiniteLoader isItemLoaded={isItemLoaded} itemCount={children.length} loadMoreItems={loadMoreItems} threshold={5} > {({ onItemsRendered, ref }) => ( <List height={500} itemCount={children.length} itemSize={itemHeight} initialScrollOffset={initialOffset} onItemsRendered={onItemsRendered} ref={ref} width="100%" > {Row} </List> )} </InfiniteLoader> ); }; export default CustomMenuList;` 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)