15

Is it possible to take HTML/JSX content from an external source and render it in dynamically in React? In our case we want to take content from the Wordpress API and render it on both the client and the server (we're using NextJS)

So, the Wordpress API returns a JSON response which includes a content property which is a string of HTML/JSX. the content would look something like this.

{
    content: "<div><Slider imageCount="5" galleryID="1"></Slider><span>This is an image gallery</span></div>"
}

So, as you can see it would be a mix of HTML and React components/JSX, represented as a string

I would use Axios to make a call to get the content (on both server and client using NextJS's getInitialProps() method), then I need to render it, but i'm new to react and I can see a couple of problems.

1) In React, JSX is compiled at build time, not run time, I can't see how to get round this (It would have been easy in Angular using $compile service for example).

2) As we don't know what components the content from Wordpress is going to use, we'd have to import every single one of them at the top of the page, the content may include a component or it may include a component, who knows?.

Right now, I'm thinking this isn't possible, which would mean we'd have to reconsider using React, but I'm really hoping somebody has an answer.

Any help would really be appreciated.

4
  • You could maybe parse the string (with a regex matching only tags with capitals) to detect the classes used in it, and then replace those parts (<Slider ... </Slider>) with the rendered react, and then use dangerouslySetInnerHtml. Does it make sense ? Commented Jul 26, 2018 at 13:57
  • It makes sense, it's the middle bit "replace those parts with the rendered react" that I'm not sure how to do. Where would I do this? Commented Jul 26, 2018 at 14:15
  • Why instead of fetching a string that might contain JSX, you can "build" the string on save, and when fetching you will need only the bundle that is the output of that "build", using import('url-to-bundle'), and then render it with React. Commented Feb 19, 2019 at 20:46
  • while not exactly what the OP is asking, if your looking to dynamically render react components from a seperate bundle at runtime, checkout my answer here stackoverflow.com/a/61823689/800619 Commented May 15, 2020 at 16:14

3 Answers 3

10
+250

Interesting problem!

You should try react-jsx-parser. I think it solves your problems. Not sure how it works with Next JS - I have no experience with Next JS.

Check out this sandbox: Edit 24r1ypp00p


You are right about all the components getting bundled. There is a workaround for that. :)

Check out this sandbox: Edit 24r1ypp00p

I've created a dynamicComponent that expects an import promise and returns a component.

I changed the way A, B and C components are imported in index.js. This way each dynamically imported component gets a separate bundle and is only requested when needed.

This should solve your second problem.

Sign up to request clarification or add additional context in comments.

6 Comments

That's very interesting, looks like it could work on the front-end as long as I import every React component at the top of the page that the CMS might output. Going to investigate this a bit further.
react-jsx-parser seems to add the missing link: importing components in FE so they are available when/if rendered dynamically
In their example ComponentA, B, C, D are all imported at the top of the page so presumably end up in the bundle regardless of whether JSX-parser needs them to render the string. Unless I've misundersttod something.
From my limited understanding of NExtJS it renders your page on the from and back end in the same way so I shouldn't have to do anything differend for the SSR part of it but I'm going to ask the NextJS community to make sure. I'm also not sure what the security implications are of fetching a string from my CMS using Axios and then parsing it on the front end?
I've updated the answer to address the components getting all bundled. Security wise I don't know what to say :) I would call this a temporary solution until things are migrated to something easier to maintain and more straight forward. Fetching strings from CMS and rendering it on the FE might prove to be unstable and hard to maintain but it could get you some time for migration. Hope it helps!
|
0

You can refer to the below link

https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

For the React Components part you can render an Static HTML Markup string using

https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup

But be sure that the html you get is from an authentic source and will not contain any malicious scripts

4 Comments

From reading that link I'm not sure the second part will work. The markup needs to be rendered on both server and client and needs to be fully functional.
In case of a fully functional dynamic component then you will need the components in both server and client. But however need not import all the components , You can try Dynamic Imports and splitting the code int hat way all your components will not be loaded at render reactjs.org/docs/code-splitting.html
I'm sorry, I don't understand how this solves my problem. I don't need to use two different solutions fot HTML and components, I need something that will convert a string of HTML/JSX into a working react component and child components in Next JS, on front-end and back-end
You will have to import all the components at the top and use them , that is the only solution i can think of :) , I added the code splitting link as an optimization for dynamic imports
-2

You can Render external HTML/React components dynamically in React like this, simply in these quotation , content: `<div>${<Slider imageCount="5" galleryID="1"></Slider>}<span>This is an image gallery</span></div>

ends with these ` sign.

1 Comment

I don't understand how using a template literal will render my string as fully-functional React?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.