user1929437
user1929437

Reputation: 473

React non-blocking rendering of big chunks of data

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

Answers (4)

nullspace
nullspace

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

Alan
Alan

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:

  1. 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.
  2. or use a library to have a virtualized list, as another person already answered.

Upvotes: 3

Joru
Joru

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

Markus
Markus

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

Related Questions