In today's episode, we take a bite-sized approach to learning how ReactDOM.render
works and what it does!
Quick recall
In the previous episode we figured out how React.createElement
works. In short:
There are two functions:
-
createElement
- for production use -
createElementWithValidation
- for dev purposes
createElementWithValidation
uses createElement
internally, but adds validation and meaningful warnings.
createElement
returns a JS object with a bunch of properties. This object is a virtual DOM node.
For us the most important properties are:
-
type
- defines type of the element -
props
- contains all props passed to the element -
children
- contains all children of the element
How ReactDOM.render
works
Recalling the assumption
In the previous episode, we formed an assumption regarding how react-dom
works as a whole. Here it is:
react-dom
creates a real DOM structure, based on the virtual DOM, and mounts the result in the provided container.
Continue with testing the assumption
Our entry point is the render
function, it takes three arguments.
-
element
- React element to be rendered -
container
- DOM element to render in -
callback
- function to be executed after render happens
Inside render
function ReactDOM
does couple of checks.
isValidContainer
isValidContainer
checks whether the container
is a suitable node.
This check is based on a couple of comparisons, like this one.
container.nodeType === 1;
nodeType
is an integer, that indicates what the node is.
1 for Element
node, 3 for Text
node and so on.
To pass this check a container
should be either:
-
Element
- the most general class of all element objects -
Document
- the main object of the rendered DOM -
DocumentFragment
- lightweight version ofDocument
separated from the rest of the DOM
And on a one special comparison.
node.nodeType === 8 && node.nodeValue === ' react-mount-point-unstable '
This check detects whether the provided container is a comment with react-mount-point-unstable
text.
<!-- react-mount-point-unstable -->
isModernRoot
isModernRoot
validates whether the container
wasn't previously passed to createRoot
function. This check detects:
- absence of
_reactRootContainer
property. This property indicates, that element was passed to therender
function. - presence of
__reactContainer$qk4eqywqqse
property. This property indicates, that element was passed to thecreateRoot
function.$qk4eqywqqse
- is a unique hash, generated on every newReactDOM
instance
createRoot
is a new API introduced in React 18. It fixes the issue of passing the container
every time we want to explicitly render.
Old API
const container = document.querySelector('#root');
// Initial render. Container is explicitly accessed.
ReactDOM.render(<App text="Hello" />, container);
// Subsequent renders. Container is explicitly accessed.
ReactDOM.render(<App text="Hello world!" />, container);
New API
// First, we create a root
const root = ReactDOM.createRoot(document.querySelector('#root'));
// Initial render. Container is implicitly accessed.
root.render(<App name="Hello" />);
// Subsequent renders. Container is implicitly accessed.
root.render(<App name="Hello world!" />);
legacyRenderSubtreeIntoContainer
After these two checks render
passes element
, container
and callback
to the legacyRenderSubtreeIntoContainer
function and returns the result.
We'll examine what this function does and how it works in the next episode!
Wrap up
Today we learned
Today we learned, that ReactDOM.render
function is basically a wrapper for legacyRenderSubtreeIntoContainer
. But at the same time it checks a couple of crucial things:
- Is passed
container
a suitable element? - Was the
container
previously passed toReactDOM.createRoot
function?
Follow me on Twitter for daily bite-sized content like this! Let's become better engineers together!
Top comments (1)
Hi,
I was actually looking for way to create a function that can replace
React.createElement();
to Create Some React Element Like this.
const ExampleComponent=()=>{
const [state,setState] = React.useState(0);
function handleClick(e:any) {
e.preventDefault();
setState(state+1);
}
return (<>
<button onClick={handleClick}>
{state}</button>
</>);
}
Can I create Similar React Element Like ExampleComponent using
React.createElement()
?If Yes {
How Can I create ExampleComponent Using
React.createElement()
?}
I know I can User
React.element(ExampleComponent,{},React.createElement('button',{onClick:handleClick},{state});
but for this I have to create state by hand no it is not pure React.
I want to create It without JSX.