0

Hi I need to render a div element with a script inside of it:

something like:

 <div id="div-id-for-squaretile1" style="width: 300px; height: 250px;">
    <script>
      googletag.cmd.push(function() {
        googletag.display('div-id-for-squaretile1');
      });
    </script>
  </div>

I am using a hook in my component:

const GooglePublisherTag = ({ id }) => {
  useGptSlot(id);
  return <div id={id} />;
};

useGptSlot Hook looks like:

const useGptSlot = (id) => {
  useEffect(() => {
    const googletag = window.googletag || { cmd: [] };
    googletag.cmd.push(() => {
      googletag.display(id);
    });
  }, [id]);
};

However my code does not render a script within a div:

it instead outputs:

<div id="div-id-for-squaretile1" data-google-query-id="CLGYq8Hhv-cCFcfbwAodGgcK0g" style="width: 250px; height: 250px;">
  <div id="google_ads_iframe_/21848388897/Development/Geo-Landing_0__container__" style="border: 0pt none; width: 250px; height: 250px;"></div>
</div>

How do I achieve this?

Ackman
  • 1,562
  • 6
  • 31
  • 54
  • The hypothetical way is with [dangerouslySetInnerHTML](https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml). However, **that won't work** because you need to manually create ` – zero298 Feb 07 '20 at 16:08
  • so there is no way to render that script tag using react? – Ackman Feb 07 '20 at 16:30

1 Answers1

0

The hypothetical way is with dangerouslySetInnerHTML. However, that won't work because you need to manually create <script> tags with document.createElement() since scripts added through innerHTML won't actually be interpreted see also MDN.

Instead, what you might consider is using a useCallback ref to get a handle to the element that you will be creating and then manually create the <script> tag and append it where you want it. Consider the example below that will add a <script> tag as a child of the element we want and set its src to jQuery. I don't think your AdSense cares when its script loads, but for this example we wait a second and then just make sure that jQuery actually exists in our context (which demonstrates that the script ran).

const {useState, useEffect, useCallback, Fragment} = React;

function Scripter() {
  const script = useCallback(el => {
    console.log("cb");
    if(!el) {
      console.log("No el");
      return;
    }
    const s = document.createElement("script");
    el.appendChild(s);
    s.src = "https://code.jquery.com/jquery-3.4.1.js";
    
    setTimeout(() => {
      console.log("jQuery should have been loaded by now");
      console.log(typeof $);
    }, 1000);
  }, []);
  
  return (
    <div ref={script}>Hello</div>
  );
}

function App() {
  return <Scripter />;
}

ReactDOM.render(<App />, document.getElementById("app"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script>

<div id="app"></div>

However, why even bother with the script tag? googletag.display(divOrSlot) accepts an Element so I would just run the code that the script tag will contain yourself within the component.

(The code below probably won't execute as a stack snippet since it likely violates some frame policies)

const {useCallback} = React;

window.googletag = window.googletag || {cmd: []};

function useGpt(el) {
  if (!el) {
    console.log("No el provided");
    return;
  }
  
  googletag.cmd.push(function() {
    googletag.display(el);
  });
}

function DummyElement() {
  const cb = useCallback(useGpt, []);
  
  return (
    <div ref={cb}>Should get tagged</div>
  );
};

function App() {
  return <DummyElement />;
}

ReactDOM.render(<App />, document.getElementById("app"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script>
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>

<div id="app"></div>
zero298
  • 25,467
  • 10
  • 75
  • 100
  • so where do I place this scripter? Main App of my project? I am confused – Ackman Feb 07 '20 at 17:03
  • @Ackman See my edit. I don't think you should actually use a script tag as you first described. Just use the JS code like you normally would. – zero298 Feb 07 '20 at 17:22