I'm working on an app for a client who wants to display Zendesk Support article data with richer content than the API/tool supports. The API, powered by a basic WYSIWYG editor on Zendesk, is able to serve up an HTML blob with <p>
and <img>
and <a>
tags. But it's unable to, say, easily embed a video, show an image gallery, or link to another location in the app without necessitating a hard refresh.
So we decided to build out a small amount of DSL syntax whereby the client could type something that would be parsed on our app and turned into the richer content. For example:
[[ video src="youtube.com/whatever" ]]
might, on our app, be parsed out, and replaced with an iframe
embedding that video directly in the article.
I've got the above example working just fine, using all sorts of fun/problematic RegExp magic.
I'm aware that parsing HTML with RegExp is a major anti-pattern, and I'm getting around it by not really parsing HTML per se -- I'm just looking for
[[...]]
).
Basically, I parse each code out, determine what to replace it with, pass back that component, and then call ReactDOMServer.renderToString(replacementEl)
to insert the resulting HTML into the article HTML string, which is then rendered to the page using dangerouslySetInnerHtml
.
This is working great, despite all the obvious messiness issues. (I know, but the client wants a very feature-rich solution, and wants to use the Zendesk API).
Here's the problem: This solution only works when rendering HTML. It doesn't work when I try to render, for example, a <Link>
(from React Router) or a home-made <Gallery />
component.
So I'm trying to figure out if there's a good way to do this. One that ideally doesn't involve going full RegExp on the HTML blob (which is obviously a mess).
I'm guessing that the solution will involve removing the codes, converting the code-free HTML string into actual React components (as opposed to just spitting the string into another element), and then, based on some sort of ledger of where the short codes go in this new React component, inserting the contents into the page.
But I'd appreciate some suggestions if anyone has encountered a similar problem. I want to do this in a way that isn't totally crazy and brittle, though it's obviously an inherently messy problem.
EDIT: To clarify, when I say it doesn't work, what I mean is that the JavaScript associated with the React components doesn't run. If I replace a code with a <Link to="whatever" />
, for example, ReactDOMServer.renderToString
successfully turns that component into its final HTML (an <a>
tag), but nothing happens on click of that tag, because the JavaScript that's actually changing browserHistory
on a regular click just isn't run.
So maybe the more pointed question is:
Is there a way to insert React Components into an HTML string in such a way that they retain their JavaScript functionality and don't just become HTML?