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?
Another way to render a large amount of data is with infinite scroll. Infinite scroll involves appending data to the end of the page as you scroll down the list. When the page initially loads, only a subset of data is loaded. As you scroll down the page, more data is appended. There are several ways to implement infinite scroll in React.
Rendering Elements. Elements are the smallest building blocks of React apps. An element describes what you want to see on the screen: const element = <h1>Hello, world</h1>; Unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements. Note:
Applications built with just React usually have a single root DOM node. If you are integrating React into an existing app, you may have as many isolated root DOM nodes as you like. To render a React element into a root DOM node, pass both to ReactDOM.render (): It displays “Hello, world” on the page.
It calls ReactDOM.render () every second from a setInterval () callback. In practice, most React apps only call ReactDOM.render () once. In the next sections we will learn how such code gets encapsulated into stateful components.
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>
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());
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.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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With