Reputation: 473
Recently I started to learn to react and wondering, is there some kind of pattern for non-blocking UI thread rendering for big data. Let's say, we take this example: , click create a lot of items, set number for, let's say 10000, we will get frozen UI for almost 10 seconds. It updates smoothly with observables, once it is done rendering, I get that, but is there a way to render it smoothly, in chunks?
Usually, you set up some kind of array, slice it by, let's say 50, process those and setTimeout for 0 to slice another 50 and so on. Repeat til array's length is 0. Is there a pattern for react components for doing that? Maybe some plugin or until mixin?
Upvotes: 23
Views: 10522
Reputation: 963
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>
Upvotes: 6
Reputation: 458
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:
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.Upvotes: 3
Reputation: 4436
For lists as large as 10,000 items I would recommend using a virtualized list. A popular implementation of this for React is react-virtualized: http://bvaughn.github.io/react-virtualized/#/components/List.
The reason for this is that a virtualized list will only render what is visible, so it will be fast even if you have a lot of data to display. You could also split your initial render into batches, but if you do this you are likely to run into other performance issues (due to too much DOM, too many observables, etc).
Upvotes: 1
Reputation: 1636
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());
Upvotes: 4