Rendering HTML in React Js
24 April 2025 | Category: React Js
Rendering HTML is an essential part of building dynamic and interactive user interfaces in React. This tutorial will guide you through using JSX to render HTML-like content, handling dynamic HTML from user inputs or APIs, and safely rendering raw HTML using dangerouslySetInnerHTML
. We will also build a Blog Post Preview app to display formatted blog content, showcasing these concepts.
By the end, you’ll understand how to render HTML efficiently and securely in React.
What is Rendering in React?
Rendering in React refers to the process of converting React components into HTML elements that are displayed in the browser. React uses JSX, a syntax extension resembling HTML but is ultimately transformed into JavaScript for building dynamic UIs. You can also render raw HTML (e.g., from a CMS or user input), though caution is necessary to prevent security risks like cross-site scripting (XSS).
Why Learn HTML Rendering in React?
- Dynamic UIs: Render HTML based on user input, API data, or state changes.
- Reusable Components: JSX allows you to create modular, reusable UI components.
- Safe HTML Handling: Learn to render raw HTML securely to prevent vulnerabilities.
- Real-World Use Cases: Display formatted content from blogs, markdown, or editors.
Prerequisites
Before starting this guide, ensure you have the following:
- Basic knowledge of React (components, JSX, props) and JavaScript (ES6).
- Node.js and npm installed (download from nodejs.org).
- A code editor (like Visual Studio Code).
- A terminal for running commands.
We’ll be using Create React App to set up the project, which supports JSX and ES6 out of the box.
Key Concepts for Rendering HTML in React
Let’s explore the main ways to render HTML in React.
1. JSX: The Primary Way to Render HTML
JSX looks like HTML but is actually JavaScript. It allows you to write HTML-like code inside React components, which React then converts into DOM elements.
Example:
const Welcome = () => {
return <h1>Hello, React!</h1>;
};
JSX supports:
- HTML tags (
<div>
,<p>
, etc.) - Dynamic values using curly braces (
{}
) - JavaScript expressions, loops, and conditionals
2. Dynamic HTML with JavaScript
You can combine JSX with JavaScript logic to render dynamic content, such as arrays or conditional elements.
Example:
const TaskList = ({ tasks }) => {
return (
<ul>
{tasks.map((task) => (
<li key={task.id}>{task.title}</li>
))}
</ul>
);
};
3. Rendering Raw HTML with dangerouslySetInnerHTML
Sometimes, you need to render raw HTML strings (e.g., from a CMS or markdown parser). React provides dangerouslySetInnerHTML
, but it must be used carefully to avoid XSS vulnerabilities.
Example:
const RawHTML = ({ html }) => {
return <div dangerouslySetInnerHTML={{ __html: html }} />;
};
Warning: Never use dangerouslySetInnerHTML
with untrusted user input unless sanitized (using a library like DOMPurify).
Setting Up the Project
Let’s create a React app to build our Blog Post Preview app, which will render both JSX and raw HTML content.
- Create a New React App:
npx create-react-app blog-post-preview cd blog-post-preview
- Install DOMPurify: We’ll use the DOMPurify library to sanitize raw HTML for safe rendering.
npm install dompurify
- Start the Development Server:
npm start
This will open the app at http://localhost:3000. - Clean Up: In
src/App.js
, replace the content with the following:const App = () => { return ( <div> <h1>Blog Post Preview</h1> </div> ); }; export default App;
Also, deletesrc/App.css
,src/logo.svg
, and updatesrc/index.css
with:body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; } h1 { color: #333; }
Building the Blog Post Preview App
We’ll build an app that:
- Displays a blog post with title and content rendered using JSX.
- Allows users to input raw HTML (simulating CMS content) and render it safely.
Step 1: Create the Post Component
In src
, create a file named Post.js
:
const Post = ({ title, content }) => {
return (
<div style={{ backgroundColor: '#fff', padding: '20px', margin: '10px 0', borderRadius: '8px', boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)' }}>
<h2>{title}</h2>
<div>{content}</div>
</div>
);
};
export default Post;
Features:
- Uses JSX to render the post’s title and content.
- Destructures props (
{ title, content }
) for cleaner code. - Applies inline styles for simplicity.
Step 2: Create the RawHTML Component
In src
, create a file named RawHTML.js
:
import DOMPurify from 'dompurify';
const RawHTML = ({ html }) => {
const sanitizedHTML = DOMPurify.sanitize(html);
return (
<div style={{ padding: '10px', backgroundColor: '#f0f0f0', borderRadius: '4px' }} dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />
);
};
export default RawHTML;
Features:
- Uses
DOMPurify.sanitize
to clean raw HTML and prevent XSS attacks. - Renders the sanitized HTML with
dangerouslySetInnerHTML
.
Step 3: Create the PostForm Component
In src
, create a file named PostForm.js
:
const PostForm = ({ onAddPost }) => {
const [htmlContent, setHtmlContent] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (htmlContent.trim()) {
onAddPost({
title: `Post ${new Date().toLocaleTimeString()}`,
content: htmlContent,
});
setHtmlContent('');
}
};
return (
<form onSubmit={handleSubmit} style={{ marginBottom: '20px' }}>
<textarea
value={htmlContent}
onChange={(e) => setHtmlContent(e.target.value)}
placeholder="Enter raw HTML (e.g., <p>Hello</p>)"
style={{
width: '100%',
height: '100px',
padding: '10px',
marginBottom: '10px',
borderRadius: '4px',
}}
/>
<button
type="submit"
style={{
padding: '10px 20px',
backgroundColor: '#28a745',
color: '#fff',
border: 'none',
borderRadius: '4px',
}}
>
Add Post
</button>
</form>
);
};
export default PostForm;
Features:
- Manages textarea input using
useState
. - Submits raw HTML content to the parent component.
Step 4: Update the App Component
Update src/App.js
to manage posts and render the components:
import Post from './Post';
import PostForm from './PostForm';
import RawHTML from './RawHTML';
const App = () => {
const [posts, setPosts] = React.useState([
{
title: 'Sample Post',
content: <p>This is a <strong>sample</strong> post rendered with JSX.</p>,
},
]);
const addPost = (newPost) => {
setPosts([...posts, { title: newPost.title, content: <RawHTML html={newPost.content} /> }]);
};
return (
<div>
<h1>Blog Post Preview</h1>
<PostForm onAddPost={addPost} />
<div>
{posts.map((post, index) => (
<Post key={index} title={`Blog Post: ${post.title}`} content={post.content} />
))}
</div>
</div>
);
};
export default App;
Features:
- Manages an array of posts using
useState
. - Renders posts with JSX (
Post
) and raw HTML (RawHTML
).
Testing the App
- Save all files and ensure the development server is running (
npm start
). - Open http://localhost:3000 in your browser.
- You should see a sample post rendered with JSX.
- There’s a form to input raw HTML.
- New posts will render safely using
RawHTML
.
Understanding the Code
- JSX: The
Post
component uses JSX to render structured HTML (e.g.,<h2>{title}</h2>
). - Dynamic Rendering: The posts array is mapped to
Post
components, allowing dynamic rendering of posts. - Raw HTML: The
RawHTML
component usesdangerouslySetInnerHTML
with sanitized HTML (via DOMPurify) to render user-entered content safely.
Best Practices for Rendering HTML in React
- Use JSX Whenever Possible: JSX is safer and more maintainable than raw HTML. Use it for static or structured content.
- Sanitize Raw HTML: Always sanitize user input or external HTML using
DOMPurify
to prevent XSS attacks. - Avoid Inline HTML in State: Store raw HTML as strings and render it with
dangerouslySetInnerHTML
only when necessary. - Validate Input: Validate HTML input before rendering, and provide feedback for invalid input.
- Use Keys in Lists: Add a
key
prop when mapping arrays to avoid React warnings.
Common Pitfalls and Fixes
- XSS Vulnerabilities: Fix by using
DOMPurify.sanitize
to sanitize HTML. - Invalid HTML: Validate HTML or use an HTML validator before rendering.
- Performance Issues: Use JSX for static content, and optimize rendering with
React.memo
if needed. - Console Warnings: Always use a unique
key
in lists.
What’s Next?
- Add Markdown Support: Use libraries like
marked
to convert markdown to HTML. - Enhance the Form: Add title fields and input validation.
- Improve Styling: Use CSS frameworks like Tailwind CSS.
- Explore Libraries: Try
react-markdown
for rendering markdown or Slate for rich text editors.
Practice Challenge
Add a toggle button to switch between rendering raw HTML as text (e.g., <p>Hello</p>
) and rendering it as formatted HTML using RawHTML
. Use useState
to manage the toggle state.
Resources
Congratulations! You’ve now mastered HTML rendering in React. Keep practicing and happy coding!