Explain Codes LogoExplain Codes Logo

How to render HTML string as real HTML?

javascript
html-sanitization
dompurify
react-unsafe-html
Anton ShumikhinbyAnton Shumikhin·Sep 17, 2024
TLDR

To render an HTML string in your web application, you can utilize innerHTML of a target document element:

// The force awakens document.getElementById('target').innerHTML = '<p>The quick brown fox jumps over the lazy dog.</p>';

Alternatively, to add content without overwriting what's already there, go for insertAdjacentHTML:

// Yet another script kiddie tries to append HTML document.getElementById('target').insertAdjacentHTML('beforeend', '<p>The spirit of StackOverflow helps again!</p>');

Both of these methods transform your humble string into a full-fledged HTML, morphing it into the architecture of your DOM tree.

Sanitization: Your Magic Shield Against Evil

An exposed HTML string, especially those that drink from user inputs, needs a bath before it gets dressed in the DOM. This is where HTML sanitization saves the day. Libraries like DomPurify do this job perfectly, scrubbing and rubbing the not-so-clean HTML string before setting it free into the DOM-verse.

// WARNING: running the following command may save your application! npm install dompurify # Or using yarn yarn add dompurify
import DOMPurify from 'dompurify'; let userGeneratedHtml = '<a href="http://example.com" target="_blank">Hello, world!</a>'; let clean = DOMPurify.sanitize(userGeneratedHtml); document.body.innerHTML = clean;

This way, you'll ensure your application isn't serving a hot plate of XSS injections to the users.

React: The Gauntlet Has Been Thrown

In a world where React sets the rules, painting the DOM directly is seen as a taboo — a shift from the imperative to the declarative paradigm.

  • The dangerouslySetInnerHTML property is your knight in shining armor, given you use it cautiously and with sanitized HTML:
function MyComponent({ htmlString }) { // React says: Handle with care! return <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(htmlString) }} />; }
  • On duty, watching for any content changes, are useState and useEffect, the unsung heroes of dynamic reactivity in React:
import React, { useState, useEffect } from 'react'; const [htmlContent, setHtmlContent] = useState(''); useEffect(() => { // Change is the only constant const newContent = "<div>To infinity and beyond!</div>"; setHtmlContent(newContent); }, []);

React: A Tale of Parsers

To extend the power of React, libraries like react-html-parser or html-react-parser take parsing to the next level, ensuring safer and more efficient handling of strings.

// Summoning auxiliary troops npm install html-react-parser # Or using yarn yarn add html-react-parser
import React from 'react'; import parse from 'html-react-parser'; const MyComponent = ({ htmlString }) => { // Abracadabra! return <div>{parse(htmlString)}</div>; };

React Refs: InnerHTML's Secret Admirer

If you're in search of a performance boost with minimal direct DOM manipulation, React's useRef and useEffect combo is your best ally. This way, you avoid repeating calculations in the virtual DOM, saving some caffeine for your app!

import React, { useRef, useEffect } from 'react'; const MyComponent = ({ htmlString }) => { const divRef = useRef(); useEffect(() => { if (divRef.current) { // Look ma, no re-rendering! divRef.current.innerHTML = DOMPurify.sanitize(htmlString); } }, [htmlString]); return <div ref={divRef} />; };

Fine-tuning Your HTML Rendering: Dos and Don'ts

Before you decide on a method, mull over your security and performance needs. Don't render HTML content from user inputs without a good sanitize-and-rinse. Each method comes with its trade-offs; pick the one that checks most of your boxes.

Clean Code Needs Clean Tests

A well-tested implementation ensures your sanitized and rendered HTML is working exactly as expected. Test your code like you've got a potato sack race to win. Automated testing tools like Jest for React make it a walk in the park!