JavaScript not working when getting content through api

Viewed 33
  import React, { useEffect, useState } from "react";

  const Test = () => {

    useEffect(() => {
      let url = "http://127.0.0.1:8000"
      fetch(url)
      .then(res => res.text())
      .then(res => {
      document.getElementById("content").innerHTML = res;
      })
    }, [])

    return (
      <div id="content">
      </div>
    )
  }

  export default Test;

My backend code what am giving in response

       <!DOCTYPE html>
   <html>
 <head>
{% load static %}
<meta charset="utf-8"/>
<title> Velodrivers </title>
  </head>
 <body>
<div>
    <canvas id="output"></canvas>
    <video id="video" playsinline style="
          -webkit-transform: scaleX(-1);
          transform: scaleX(-1);
          visibility: hidden;
          width: auto;
          height: auto;
          ">
    </video>
</div>

<div>
    <label for="color"> Color {{ pallet }} </label>
    <input id="color" type="color" value="" />

    <label for="opacity"> Strength </label>
    <input id="opacity" type="range" min="0" max="1" step="0.01"/>
</div>
</body>

 <script src='{% static "main.js" %}'></script>

   </html>     

My backend returns response as a html element which contains html css and javascript. from react i am making the api call and getting the html content as well as add to innerHTML. But the javascript functionality is not working.

The backend html code opens webcam that is not working here because thatopens using javascript.

Please take a look how can i make it work.

2 Answers

you are using react and state need to be use like this:

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

  const Test = () => {

    const [data, setData] = useState([]);

    useEffect(() => {
      let url = "http://127.0.0.1:8000"
      fetch(url)
      .then(res => res.text())
      .then(res => {
      //document.getElementById("content").innerHTML = res;
      setData(res)
      })
    }, [])

    return (
      <div id="content">

      {data.map((item)=> {
       <li>{item.name}</li> 
      })}
      </div>
    )
  }

  export default Test;

Issue

document.getElementById("content").innerHTML = res; is a direct DOM mutation, an anti-pattern in React.

Solution

React works by storing state and updating it. When state is updated then the component rerenders with the updated state. See useState.

Since it seems you are sending raw HTML from your backend then you can sanitize and render this via dangerouslySetInnerHTML

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

const Test = () => {
  const [data, setData] = useState(null); // <-- create state

  useEffect(() => {
    let url = "http://127.0.0.1:8000"
    fetch(url)
    .then(res => res.text())
    .then(res => {
      setData(res); // <-- update state
    })
  }, [])

  return (
    <div id="content">
      {data && <div dangerouslySetInnerHTML={{ __html: data }} />} // <-- render html
    </div>
  )
}
Related