Reputation: 309
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.
Upvotes: 1
Views: 1254
Reputation: 121
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.
Upvotes: 2
Reputation: 4207
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>
);
}
Upvotes: 1
Reputation: 26
Try:
let objectData = parse(`<div className="App">${unescapedVizCode}</div>`);
return objectData;
Upvotes: 0
Reputation: 1702
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");
Upvotes: 0