Hacking React’s JSX Into Pure JavaScript: Document Fragments
There is no doubt that React is an amazing framework. When I first began learning JSX, React’s unique way of rendering HTML elements to the document, I was put off. I had just become accustomed to rendering elements with pure JavaScript through the method I’m sure we all know:
let myDiv = document.createElement(‘div’);
myDiv.innerText = “hey this is my div!”;
myDiv.classList.add(‘myDiv’);
document.body.appendChild(myDiv);
I naively thought that to be the best solution. I couldn’t see at the time how much faster React’s component-based elements were. Within a week of using React I was in love. I had already come to appreciate writing my own functions to render all my favorite elements to the page to try and speed up the clunky methodology of pure JavaScript, and React’s components makes that process significantly faster.
But React isn’t always the solution. React adds weight to your project, and it can be a lot for a static page or simple web application. Sometimes regular old JavaScript is the best option. But going from React’s components to the old way of rendering elements with JavaScript is a sad experience to say the least. There has got to be a better way!
And there is! We can convert strings to HTML nodes using
document.createRange().createContextualFragment(string);
This function returns a document fragment object that can be appended to the DOM. This makes writing functional HTML much faster. Let’s look at an example.
Say we want to write a function to render a warning to our DOM. This function will take arguments for where the document fragment should be rendered, as well as what text the warning should have. We’ll start by creating a function to return just the document frag, so you can see what the code looks like:
Here, we’re writing HTML in a string, then feeding that string to the document.createRange().createContextualFragment(returnString); function. We’re using a template literal so we can easily access variables fed through the options argument. But since template literals don’t support the use of iterator functions like .forEach, we can use standard strings if necessary, like for iterating through an array and returning one string containing all of the HTML.
Now that we have a function to make the document fragment, let’s create a function to render it to our page:
And that’s all there is to it! Now we can call this function and get our warning div:
And if we want to animate that element when it is rendered using the web animation API, we can include it in the function. We have to include it after the element has been rendered to the DOM, and we cannot animate the document fragment itself, so we have to target an element inside the document fragment. Here we’re targeting the last element with the .warningCard class, as that would probably always be the warning element we want.
And that’s all there is to it!
I think this method is much faster than using 2 or more lines to create each element, give that element a class or id, change its text or other properties, and render it to the page. And it gives JavaScript a more JSX feel in that you can create functions for returning one type of reusable element, complete with taking an object as an argument and parsing that object for specific keys to customize the returned element. And if you’d like, you can even style the element inline, similar to Styled Components in React (though without the added benefit of Styled Component’s other features like pre-processing).
Final Thoughts
So, going forward, will I use document fragments for my pure JavaScript projects? Probably. I think they’re easier to write and probably easier to understand for developers that are familiar with HTML (to the benefit of others reading your code). I think they’re criminally under-used — no one I’ve geeked out to about them has had any idea what I’m talking about! I think in a bizarre alternate world where great frameworks like React, Vue, and Angular didn’t come to dominate our front ends and pure JavaScript somehow became king, document fragments would be the standard.
But this is not that world, and those frameworks do reign supreme, and employers are looking to hire React devs, and I’m going to go back to learning more React instead of spending time on niche features of JavaScript now 😅