React js 18 What is "Rendering" and whats new ?

Rendering is the process of React asking your components to describe what they want their section of the UI to look like, now, based on the current combination of props and state.

Rendering Process Overview

During the rendering process, React will start at the root of the component tree and loop downwards to find all components that have been flagged as needing updates. For each flagged component, React will call either classComponentInstance.render() (for class components) or FunctionComponent() (for function components), and save the render output.

A component's render output is normally written in JSX syntax, which is then converted to React.createElement() calls as the JS is compiled and prepared for deployment. createElement returns React elements, which are plain JS objects that describe the intended structure of the UI. Example:

------

// This JSX syntax:
return <SomeComponent a={42} b="testing">Text here</SomeComponent>

// is converted to this call:
return React.createElement(SomeComponent, {a: 42, b: "testing"}, "Text Here")

// and that becomes this element object:
{type: SomeComponent, props: {a: 42, b: "testing"}, children: ["Text Here"]}

------

After it has collected the render output from the entire component tree, React will diff the new tree of objects (frequently referred to as the "virtual DOM"), and collects a list of all the changes that need to be applied to make the real DOM look like the current desired output. The diffing and calculation process is known as "reconciliation".

React then applies all the calculated changes to the DOM in one synchronous sequence.

 

Note: The React team has downplayed the term "virtual DOM" in recent years. Dan Abramov said:

I wish we could retire the term “virtual DOM”. It made sense in 2013 because otherwise people assumed React creates DOM nodes on every render. But people rarely assume this today. “Virtual DOM” sounds like a workaround for some DOM issue. But that’s not what React is.
React is “value UI”. Its core principle is that UI is a value, just like a string or an array. You can keep it in a variable, pass it around, use JavaScript control flow with it, and so on. That expressiveness is the point — not some diffing to avoid applying changes to the DOM.
It doesn’t even always represent the DOM, for example <Message recipientId={10} /> is not DOM. Conceptually it represents lazy function calls: Message.bind(null, { recipientId: 10 }).

 

Render and Commit Phases

The React team divides this work into two phases, conceptually:

  • The "Render phase" contains all the work of rendering components and calculating changes
  • The "Commit phase" is the process of applying those changes to the DOM

After React has updated the DOM in the commit phase, it updates all refs accordingly to point to the requested DOM nodes and component instances. It then synchronously runs the componentDidMount and componentDidUpdate class lifecycle methods, and the useLayoutEffect hooks.

React then sets a short timeout, and when it expires, runs all the useEffect hooks. This step is also known as the "Passive Effects" phase.

You can see a visualization of the class lifecycle methods in this excellent React lifecycle methods diagram. (It does not currently show the timing of effect hooks, which is something I'd like to see added.)

In React's upcoming "Concurrent Mode", it is able to pause the work in the rendering phase to allow the browser to process events. React will either resume, throw away, or recalculate that work later as appropriate. Once the render pass has been completed, React will still run the commit phase synchronously in one step.

A key part of this to understand is that "rendering" is not the same thing as "updating the DOM", and a component may be rendered without any visible changes happening as a result. When React renders a component:

  • The component might return the same render output as last time, so no changes are needed
  • In Concurrent Mode, React might end up rendering a component multiple times, but throw away the render output each time if other updates invalidate the current work being done