Issue Overview
I’m utilizing a content management system where editors are allowed to input custom JavaScript within a rich text editor. The content may consist of external scripts and CSS styles that must function correctly on the frontend.
Example of editor content:
<script>
window.config = 'dashboard';
</script>
<script defer src="/assets/js/vendor.js?v=2"></script>
<script defer src="/assets/js/main.js?v=2"></script>
<link href="/assets/css/styles.css?v=2" rel="stylesheet">
Implementation in React Component
I have developed a component that should render this content by leveraging a custom parser:
import { graphql } from "gatsby";
import React from "react";
import { Container, Row, Col } from "react-bootstrap";
import ContentParser from "../../components/ContentParser";
import PageHead from "../../components/PageHead";
const ContentPage = ({ pageData }) => {
return (
<Container className="content-wrapper">
<Row>
<Col>
<ContentParser
htmlContent={pageData?.contentNode?.body?.processed}
/>
</Col>
</Row>
</Container>
);
};
export default ContentPage;
export const query = graphql`
query ($slug: String!) {
contentNode(id: { eq: $slug }) {
title
body {
processed
}
seo {
metaDescription
metaKeywords
}
url {
path
}
featured {
featuredImage {
src
}
}
}
}
`;
ContentParser component:
import React from "react";
import parseHtml from "html-react-parser";
const ContentParser = ({ htmlContent, customClasses }) => {
const processedContent = parseHtmlContent(htmlContent);
return (
<div className={`parsed-content ${customClasses || ''}`}>
{processedContent}
</div>
);
};
function parseHtmlContent(content) {
return parseHtml(content, {
replace: (element) => {
if (element.name === 'img') {
return (
<img
src={element.attribs.src}
alt={element.attribs.alt || 'Content image'}
className="responsive-image"
loading="lazy"
/>
);
}
return element;
}
});
}
export default ContentParser;
The Problem
After transitioning from dangerouslySetInnerHTML
to the custom parser, I encountered hydration errors like:
Text content does not match the server-rendered HTML
Hydration failed due to mismatch between server-rendered UI and client-rendered UI
There was an error during hydration
The external JavaScript is not executing anymore, causing third-party widgets to fail to display. What steps can I take to address these hydration issues while correctly parsing and rendering rich text content that includes embedded scripts?