Unelma.dev

loading...

ReactDOM.createRoot ๐Ÿ†š ReactDOM.render

Amit Kalwar
ใƒป3 min read

https://unelma.io/9LXP0
What is ReactDOM.createRoot and how is it different from ReactDOM.render?

React 18 introduces a new root API, so let's figure it out

๐Ÿ‘‰ Current API

We have to pass the container to render function every time we want to explicitly render.
const container = document.querySelector('#root');

// Initial render. Container is explicitly accessed.
ReactDOM.render(, container);

// Subsequent renders. Container is explicitly accessed.
ReactDOM.render(, container);
๐Ÿ‘‰ What does ReactDOM.render take?

render function takes three arguments:

React element to be rendered
DOM element to render in
function to be executed after render happens
And returns the same container, but with the rendered component.
/**

  • @param element - React element to be rendered
  • @param container - DOM element to render in
  • @param callback - function to be executed after render happens
  • @return container - container with renderned component */ function render(element, container, callback) { // ... } ๐Ÿ‘‰ How does ReactDOM.render work under the hood?

ReactDOM.render does a couple of validation checks:

whether the container is a suitable node
whether the container wasn't previously passed to createRoot
Then it passes all received arguments to legacyRenderSubtreeIntoContainer.
// simplified structure
function render(element, container, callback) {
if (isValidContainer(element)) {
throw Error('Target container is not a DOM element.');
}

if (isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined) {
// don't throw an error, but logs it into console
error('container was previously passed to ReactDOM.createRoot().');
}

return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
}
๐Ÿ‘‰ New API

It fixes the issue of passing the container every time we want to explicitly render.
// First, we create a root
const root = ReactDOM.createRoot(document.querySelector('#root'));

// Initial render. Container is implicitly accessed.
root.render();

// Subsequent renders. Container is implicitly accessed.
root.render();
๐Ÿ‘‰ What does ReactDOM.createRoot take?

createRoot function takes only one mandatory argument - DOM element to render in.
And returns RootType, which has render and unmount methods.

P.S. Also createRoot takes the second RootOptions argument, but we'll examine it in the future.
/**

  • @param container - DOM element to render in
  • @param options - options, related to hydration
  • @return RootType - instance of root */ function createRoot(container, options) { // ... } ๐Ÿ‘‰ How does ReactDOM.createRoot work under the hood?

On top of the render function, createRoot:

checks whether the container isn't a body element
provide a bit more detailed warnings
Then createRoot instance a new ReactDOMRoot object and returns it. No legacyRenderSubtreeIntoContainer at all!
// simplified structure
function createRoot(container, options) {
if (isValidContainer(element)) {
throw Error('Target container is not a DOM element.');
}

if (container.nodeType === 1 && container.tagName.toUpperCase() === 'BODY') {
console.error('Creating roots directly with document.body is discouraged');
}

if (isContainerMarkedAsRoot(container) {
if (container._reactRootContainer) {
console.error('container was previously passed to ReactDOM.render().')
} else {
console.error('container has already been passed to createRoot() before.');
}
}

return new ReactDOMRoot(container, options);
}
Now you know the underline difference between old render and new createRoot functions!

Let me know, if you want a further comparison of legacyRenderSubtreeIntoContainer and new ReactDOMRoot.

P.S. Follow me on Twitter for more content like this!

unknown tweet media content
Nick | React tinkerer โš›๏ธ profile imageNick | React tinkerer โš›๏ธ@fromalinetwitter logo
How are React Fragments implemented?

React aims to stay neat and clean, that's why fragments are out there. They allow getting rid of excess wrappers while rendering multiple elements!

That's pretty cool, but how do they work under the hood?

FrontEnd #ReactJS #webdev

๐Ÿงต๐Ÿ‘‡
17:34 PM - 25 Jan 2022

Discussion (0)