React's default way of appending itself to a DOM tree considered harmful
William ?????? Ghelfi
Remote Full-stack Developer with a preference for Frontend ?????? (Developer experience / DevX, TypeScript, React, Nx) | Strategic Thinker ? | Gitpod Community Hero ????♂? | Nx enthusiast ??
(Originally published at https://www.williamghelfi.com/blog/2022-06-02-react-dom-harmful/)
For the impatient
Don't do this
<body>
<div id="root"></div>
</body>
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
Do this instead
<body>
<div data-role-react-root></div>
</body>
const rootElement = document.querySelector('[data-role-react-root]'),
ReactDOM.render(<App />, rootElement);
Or, as?Andrew Luca?once offered: go even deeper!
const rootElement = document.body.appendChild(document.createElement('div'));
ReactDOM.render(<App />, rootElement);
What am I talking about?
If you ever dabbled in React or followed even?the most basic of its tutorials, chances are you'll find the following snippet quite familiar:
<!-- here reduced to the bare minimum for simplicity's sake -->
<body>
<div id="root"></div>
</body>
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
This?<div id="root"></div>?plus the accompanying JavaScript snippet, or one of their variants, are everywhere: tutorials, official docs, tools like Create React App and Nx, online samples... everywhere.
Here's why this is bad to the point of being harmful.
Why is it harmful
In a nutshell:
<div class="some-class"></div>
<a href="#pricing">Pricing</a>
<!-- more code -->
<section id="pricing">
<!-- awesome pricing table -->
</section>
<div data-special>Such special, much data</div>
This separation of concerns (styling?via?classes,?navigation?via?ids,?special meaning?via?data attributes) helps avoiding some harmful situations you most certainly?will?find yourself in at some point in your career if you keep using?<div id="root"></div>?as a React root element.
Harmful situation #1
<div id="root"></div>
#root {
border: 2rem furry pink;
}
Then, in a rare flash of love for his job, Alan the designer searches the codebase for places where?id="root"?is used.
Alan finds our friend?<div id="root"></div>.
Alan thinks he just removed the one and only reason for it to exist, and deletes the whole line.
领英推荐
A sip of coffee, a deploy to production, and the job is done just before the important meeting.
Chaos ensues.
Harmful situation #2
<div id="root"></div>
<div id="react-base"></div>
ReactDOM.render(<App />, document.getElementById('react-base'));
Chaos ensues.
Conclusions
Both of these harmful situations happened to me multiple times over the last 20 years.
At first, I was Alan or Xyz, more recently I was Bob or Sue.
We had the knowledge to avoid it. Something we learnt during the first months of our careers.
Something some old dude taught us and we forgot.
What's the best practice
So what was the old dude rambling about?
When working with HTML, CSS, and JavaScript:
Or, on the other hand:
Separation of concerns.
Works wonders, if you remember about it.
FAQ and counterpoints
Isn't?document.getElementById()?supposed to be faster than?document.querySelector()?
It is! If you are selecting dozens of elements in a couple seconds.
Is it still faster when selecting one single element while the app is starting up? Probably. Will the user notice? No way.
This is only your opinion, nobody else considers it harmful!
Totally my opinion, coming from my own experience. Wish you'll never have to experience any of the situations you just read about. Take care! ??