React non-blocking rendering of big chunks of data
You can use requestIdleCallback
to defer the render:
function DeferredRender({ children, idleTimeout }) { const [render, setRender] = React.useState(false); React.useEffect(() => { if (render) setRender(false); const id = requestIdleCallback(() => setRender(true), { timeout: idleTimeout }); return () => cancelIdleCallback(id); }, [idleTimeout]); if (!render) return null; return children;}
<DeferredRender idleTimeout={1000}> <ExpensiveStuff /></DeferredRender>
React Concurrent Mode is solving the UI stall problem. You can watch some talks [1] [2] to understand how. This doesn't make your UI magically update faster, it only helps you make the UI not freeze while your UI updates.
Your two options are to either:
- update the state in chunks, as you said. If you chunk the work don't just do so based on time: you can't hard-code an optimal value based on time because people's computers perform differently. Instead either use the browser APIs like
requestIdleCallback
or look into the scheduler NPM library (https://philippspiess.com/scheduling-in-react/) in order to do the work as aggressively as possible but in a scheduled manner that doesn't lead to browser hangs. - or use a library to have a virtualized list, as another person already answered.
For a similar problem, I chunked my data and then serialized the processing with reduce
and promises:
chunks.reduce( (previousPromise, nextChunk) => { return previousPromise.then(processChunkAndUpdateComponentStateAsPromise(nextChunk));}, Promise.resolve());