React setState inside script text content

Viewed 298

Hi guys!
I'm working on the upload image feature into Cloudinary using ReactJS from the client side, then I met a problem.
Description
I added a script tag inside a component with some lines of code inside React.useEffect function. Inside the script tag, I had the data of Cloudinary return when it fetches successfully, and I wanted to get the data by using setState inside the script content. But I cannot get the data.
Question
How can I use setState inside a string? Or is there any way to get the data that was returned inside a string?

Here is my code.

React.useEffect(() => {

const scriptCloudinaryCdn = document.createElement('script');
scriptCloudinaryCdn.src =
  'https://upload-widget.cloudinary.com/global/all.js';
scriptCloudinaryCdn.async = true;



const widgetScript = document.createElement('script');

 // I wanted to get the data that was returned from this
const widgetContent = `  var myWidget = cloudinary.createUploadWidget({
  cloudName: 'cloudname', 
  uploadPreset: 'upload_preset'}, (error, result) => { 
    if (!error && result && result.event === "success") {
       // this is the data from Cloudinary, I wanted to carry this with setState
      console.log('Done! Here is the image info: ', result.info); 
  
    }
  }
)

document.getElementById("upload_widget").addEventListener("click", function(){
    myWidget.open();
  }, false);`;

widgetScript.text = widgetContent;

document.body.appendChild(scriptCloudinaryCdn );
document.body.appendChild(widgetScript);

   return () => {
     document.body.removeChild(scriptCloudinaryCdn );
     document.body.removeChild(widgetScript);
   };
}, []);

Thank you guys very much!

1 Answers

You can create some global event-emitter instance (for example using this library), subscribe to an event in react component, and then emit the event from widget's success callback.

If you do not want to use global emitter, you can use DOM event emitter instead, like so:

const [uploadedImageData, setUploadedImageData] = useState(null);

useEffect(() => {
  const onImageUplaoded = (event) => {
    setUploadedImageData(event.detail);
  };

  document.getElementById("upload_widget").addEventListener('imageuploaded', onImageUploaded);

  return () => {
    document.getElementById("upload_widget").removeEventListener('imageuploaded', onImageUploaded);    
  }
}, []);

and inside of your widget's success callback you can do:

uploadPreset: 'upload_preset'}, (error, result) => { 
  if (!error && result && result.event === "success") {
    const event = new CustomEvent('imageuploaded', { detail: result.info });
    document.getElementById("upload_widget").dispatchEvent(event);
  }
}

Of course you can think about improvements; this is just one of ideas how to solve your problem.

Related