0

Is there a way to render an html + javascript response from an API in React?

Based on this question I can render html with dangerouslySetInnerHTML={html}. My problem is the html response from the API also contains javascript as it is a vega visualisation.

Placing my whole static page into public as a file works with <a href="vega_example.html">Redirect to Html page</a>. The disadvantage of this redirect is that I don't want to save a file for every API response.

Is there a way I can render a string as a static html page with React without saving it in a file?

App.js to render static page using the public file in public folder

import React, { useEffect, useState } from 'react';

function MyComponent() {
    
  const [html, setHTML] = useState({__html: ""});

  useEffect(() => {
    async function createMarkup() {
      const backendHtmlString = `<a href="vega_example.html">Redirect to Html page</a>`

       console.log(backendHtmlString)
        return {__html: backendHtmlString};
     }
     
     createMarkup().then(result => setHTML(result));
  }, []);

  return <div dangerouslySetInnerHTML={html} />;
}

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

export default App;

In public I have vega_example.html which is pretty much my API response

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
</head>
<body>
  <div id="vis"/>
  <script>
    const spec = {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "A simple bar chart with embedded data.",
  "data": {
    "values": [
      {"a": "A", "b": 28},
      {"a": "B", "b": 55},
      {"a": "C", "b": 43},
      {"a": "D", "b": 91},
      {"a": "E", "b": 81},
      {"a": "F", "b": 53},
      {"a": "G", "b": 19},
      {"a": "H", "b": 87},
      {"a": "I", "b": 52}
    ]
  },
  "mark": "bar",
  "encoding": {
    "x": {"field": "a", "type": "nominal", "axis": {"labelAngle": 0}},
    "y": {"field": "b", "type": "quantitative"}
  },
  "config": {}
};
    vegaEmbed("#vis", spec, {mode: "vega-lite"}).then(console.log).catch(console.warn);
  </script>
</body>
</html>

1 Answer 1

1

Answering your literal question, you could either:

  • Render the content to an iFrame (the rendering being done by JavaScript calls, not React calls)
  • (Would strongly recommend against) Use RegEx to extract the contents of <script/> and use eval to run that JavaScript

However, I would instead recommend either:

  • Assuming the API only serves the JSON data, render the #vis element with React, load the JSON data in the hook, and then run vegaEmbed directly at the end of the hook.
  • If the API is dynamic, simply link to the API directly and let it serve the HTML dynamically instead of saving it as a file.
Sign up to request clarification or add additional context in comments.

Comments

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.