1

I'm getting an HTML string from an AJAX request, that looks something like that:

<div> <SpecialComponent/> <SecondSpecialComponent/></div>

What i need, is to be able use this string in a React component, as it were valid JSX.

I tried using the dangerouslySetInnerHTML as instructed in this discussion: how-to-parse-html-to-react-component

I've also tried React libraries like react-html-parse and html-react-parser. No success

When i was working with AngularJS(1), i was using some small directive that would take care of that situation. I need to achieve the same with React. Any ideas?

EDIT: if anybody is interested, i found a library that takes care of the issue: https://www.npmjs.com/package/react-jsx-parser

i.brod
  • 3,993
  • 11
  • 38
  • 74
  • can you post the html string or small template here , because if it was html using dangerouslySetInnerHTML should work fine – Fadi Abo Msalam Mar 21 '18 at 14:30
  • What was wrong with using `dangerouslySetInnerHTML`? – Stretch0 Mar 21 '18 at 14:36
  • What you are trying to do requires the content to be transpiled because it contains `jsx`. This will be very hard. Instead if you control the endpoint you are better off only returning json serializable data that can be rendered by components. – trixn Mar 21 '18 at 14:43
  • to Stretch0: it just didn't work, no matter how i tried. also in this example here it doesn't work: https://codesandbox.io/s/WnKvoY6BE. to trixin: well this would undermine the whole idea behind what im trying to build...so, i need to make it work :-) – i.brod Mar 21 '18 at 14:45
  • Don't confuse jsx with traditional html markup. `jsx` transpiles to javascript code. What you are trying to do is basically giving the client untranspiled code that first needs to be transpiled to javascript that the browser can actually understand and then execute that code somehow. – trixn Mar 21 '18 at 14:48
  • @sheff2k1 Can you give some insights about your idea then? Because if you really want to make that work it will be really hard to achieve. `jsx`may look like markup but it actually is code. – trixn Mar 21 '18 at 15:11
  • @sheff2k1 example in sandbox works fine – Tomasz Bubała Mar 21 '18 at 15:13
  • 1
    @TomaszBubała No it doesn't work fine. If you inspect the DOM you will see that it didn't render a component but an invalid html node ``. Depending on the browser it may render it anyways. But it's not a react component at all. This is just due to the fact that `jsx` can look like valid html markup but it isn't. – trixn Mar 21 '18 at 15:16
  • So, what im trying to build is simple(worked for me in AngularJs): a simple CMS system, that will allow a user to construct custom pages using a text editor. The front end of the site will be built with React, backend with PHP. The idea is, to let him "push" react components into this editor. This way, i could render very dynamic content in that page. If i just render simple HTML, i wont be able to use any "widgets"(or how ever we want to call it) inside that page. I'm sure there is a better way to achieve this, but this is already a method im familiar with, from a different project. – i.brod Mar 21 '18 at 15:43

2 Answers2

-1

You're not supposed to be doing things this way. Although React components look like html tags when using JSX, they are actually either classes or functions. What you're trying to do is equivalent to trying to parse:

"<div>document.write('foo')</div>"

You're literally mixing a javascript function name in string form with html markup in the same string. You will have to parse the string to separate the React component from the surrounding html markup, map the React components in string form to their actual React counterparts, and use ReactDOM.render to add the component to the page.

let mapping = [
    {"name":"<SpecialComponent/><SecondSpecialComponent/>","component":<SpecialComponent/><SecondSpecialComponent/>},
    {"name":"<someOtherComponent/><someOtherComponent/>","component":<someOtherComponent/><someOtherComponent/>}
];
let markup = "<div><SpecialComponent/><SecondSpecialComponent/></div>";
let targetComponent;

mapping.forEach((obj) => {if(markup.indexOf(obj.name)>-1){
    targetComponent=obj.component;//acquired a reference to the actual component
    markup.replace(obj.name,"");//remove the component markup from the string
    }
});

/*place the empty div at the target location within the page 
give it an "id" attribute either using element.setAttribute("id","label") or 
by just modifying the string to add id="label" before the div is placed in 
the DOM ie, <div id='label'></div>*/

//finally add the component using the id assigned to it

ReactDOM.render(targetComponent,document.getElementById("label"));

Never tried this before. I wonder if this will actually work :)

webnetweaver
  • 192
  • 8
  • This may even work but it is very simplified. If I understand OP correctly he wants to use it in a fully fledged CMS system. There exist some libraries that can dynamically render `jsx` but it's more intended to be used as an interactive playground. [react-live](https://github.com/FormidableLabs/react-live) is one of them. – trixn Mar 21 '18 at 16:01
  • To be honest...i didn't really understand what's going on there. But i understand it's quite similar to what is described here, which i managed to implement: https://alexvab.com/posts/how-to-dynamically-render-react-js-components This is already a good start. i could create an object that holds references to all relevant components that i might need, and then do some manipulations on the HTML string that i receive from the server, to output those elements. Will be very messy to implement, being that i might need to pass props. in my AngularJS implementations it was all just parsed as is... – i.brod Mar 21 '18 at 16:15
-2

my suggestion is you do something like the following.

first set a state variable to equal the HTML you want to return

this.setState({html: response.data.html})

then in your return you can do the following

   return ( 
   {this.state.html} 
   );
  • React escapes strings that contain html. This will render as a string and not as markup. Also in OPs case the markup is actually jsx and not html. – trixn Mar 21 '18 at 14:40