How do I render a div and script tags in React?

970 Views Asked by At

The react application received a visualization code, and I used the unescape function to get the HTML codes in string. The string has a div tag with the id of the visualization and script tag that consists of the javascript to generate the visualization.

import React from "react";
import parse from "html-react-parser";

export default function App() {
  // This code is received from the backend
  const vizCode =
    "%3Cdiv%20id%3D'chartdiv_1614071920146'%3E%3C%2Fdiv%3E%3Cscript%20type%3D'text%2Fjavascript'%3E%20var%20width_1614071920146%20%3D%20700%3Bvar%20height_1614071920146%20%3D%20700%3Bvar%20chart_1614071920146%20%3D%20c3.generate(%7Bbindto%3A%20'%23chartdiv_1614071920146'%2C%20size%3A%20%7B%20width%3A%20(width_1614071920146%20-%2020)%2C%20height%3A%20(height_1614071920146%20-%2020)%20%7D%2C%20data%3A%20%7Bcolumns%3A%20%5B%20%5B'%20'%2C%201.0%2C%201.0%2C%203.0%2C%205.0%2C%205.0%5D%20%5D%2C%20type%3A%20'spline'%7D%2C%20legend%3A%20%7Bshow%3Afalse%7D%2C%20axis%3A%20%7B%20x%3A%20%7B%20type%3A%20'category'%2C%20categories%3A%20%5B'New%20Course'%2C'group%20course%201'%2C'Testkurs%20'%2C'test_course'%2C'Moodle4CollaborativeMOOCs'%5D%20%7D%20%7D%7D)%3B%3C%2Fscript%3E";
  const unescapedVizCode = unescape(vizCode);
  console.log(unescapedVizCode);
  // Output -> <div id='chartdiv_1614071920146'></div><script type='text/javascript'> var width_1614071920146 = 700;var height_1614071920146 = 700;var chart_1614071920146 = c3.generate({bindto: '#chartdiv_1614071920146', size: { width: (width_1614071920146 - 20), height: (height_1614071920146 - 20) }, data: {columns: [ [' ', 1.0, 1.0, 3.0, 5.0, 5.0] ], type: 'spline'}, legend: {show:false}, axis: { x: { type: 'category', categories: ['New Course','group course 1','Testkurs ','test_course','Moodle4CollaborativeMOOCs'] } }});</script> 

  let objectData = parse(unescapedVizCode);
  let divData = objectData[0];
  let scriptData = objectData[1].props.dangerouslySetInnerHTML.__html;

  return (
    <div className="App">
      {objectData}
    </div>
  );
}

Here I have provided the codesandbox link

I used the dangerouslySetInnerHtml to display the visualization but unable to visualize the chart. I have added a test.html in the public folder to show the visualization in a browser. Any help is much appreciated.

4

There are 4 best solutions below

0
On BEST ANSWER

React/JSX doesn't deal with script tags. You have to explicitly load it. I'd suggest you use a hook when the component is available.

  useEffect(() => {
    const script = document.createElement('script');
    script.innerHTML = scriptData;
    document.getElementById('root').appendChild(script);
    return () => {
      document.getElementById('root').removeChild(script);
    };
  }, []);

Working example here: https://codesandbox.io/s/render-c3d3-charts-in-react-forked-4xkt9?file=/src/App.js

btw. Please don't use 'unescape', it is deprecated. Use 'decodeURIComponent' instead.

0
On

I am not sure if it satisfies your requirement, but you can use window.open to render the HTML code within iFrame or in a new tab.

To open in iFrame use the following code:

const unescapedVizCode = unescape(vizCode);
window.open(unescapedVizCode, "myFrame");
return (
<div className="App">
<iframe name="myFrame"></iframe>
  {objectData}
</div>
);

Or you can open in new tab:

const unescapedVizCode = unescape(vizCode);
window.open(unescapedVizCode, "_blank");
0
On

Try:

let objectData = parse(`<div className="App">${unescapedVizCode}</div>`);

return objectData;
0
On

Okay this answer does what you want, but I have to say: Only use this if you know 100% where the vizCode comes from and that it can be trusted! be sure to check out the reasons why you should not use eval

Your problem is, that the script content is not being executed by the browser. I tried your sandbox and it immediately worked when I added

eval(scriptData)

Here's the entire code that's working for me:

export default function App() {
  // This code is received from the backend
  const vizCode =
    "%3Cdiv%20id%3D'chartdiv_1614071920146'%3E%3C%2Fdiv%3E%3Cscript%20type%3D'text%2Fjavascript'%3E%20var%20width_1614071920146%20%3D%20700%3Bvar%20height_1614071920146%20%3D%20700%3Bvar%20chart_1614071920146%20%3D%20c3.generate(%7Bbindto%3A%20'%23chartdiv_1614071920146'%2C%20size%3A%20%7B%20width%3A%20(width_1614071920146%20-%2020)%2C%20height%3A%20(height_1614071920146%20-%2020)%20%7D%2C%20data%3A%20%7Bcolumns%3A%20%5B%20%5B'%20'%2C%201.0%2C%201.0%2C%203.0%2C%205.0%2C%205.0%5D%20%5D%2C%20type%3A%20'spline'%7D%2C%20legend%3A%20%7Bshow%3Afalse%7D%2C%20axis%3A%20%7B%20x%3A%20%7B%20type%3A%20'category'%2C%20categories%3A%20%5B'New%20Course'%2C'group%20course%201'%2C'Testkurs%20'%2C'test_course'%2C'Moodle4CollaborativeMOOCs'%5D%20%7D%20%7D%7D)%3B%3C%2Fscript%3E";
  const unescapedVizCode = unescape(vizCode);
  console.log(unescapedVizCode);

  let objectData = parse(unescapedVizCode);
  let divData = objectData[0];
  let scriptData = objectData[1].props.dangerouslySetInnerHTML.__html;
  useEffect(()=>{
    eval(scriptData)
  }, [scriptData])
  return (
    <div className="App">
      {objectData}

    </div>
  );
}