JS code works when i paste it on console, but does not work inside my React App

Okay so, there is that code:

var iyziInit = {
  currency: "TRY",
  token: "23bfa27a-172a-493d-b42f-8b091589eaa0",
  price: 2.4,
  locale: "tr",
  baseUrl: "https://sandbox-api.iyzipay.com",
  merchantGatewayBaseUrl: "https://sandbox-merchantgw.iyzipay.com",
  registerCardEnabled: true,
  bkmEnabled: true,
  bankTransferEnabled: false,
  bankTransferRedirectUrl: "https://localhost:3000/callback",
  bankTransferCustomUIProps: {},
  campaignEnabled: false,
  creditCardEnabled: true,
  bankTransferAccounts: [],
  userCards: [],
  fundEnabled: true,
  memberCheckoutOtpData: {},
  force3Ds: false,
  isSandbox: true,
  storeNewCardEnabled: true,
  paymentWithNewCardEnabled: true,
  enabledApmTypes: ["SOFORT", "IDEAL", "QIWI", "GIROPAY"],
  payWithIyzicoUsed: false,
  payWithIyzicoEnabled: true,
  payWithIyzicoCustomUI: {},
  buyerName: "John",
  buyerSurname: "Doe",
  merchantInfo: "",
  cancelUrl: "",
  buyerProtectionEnabled: false,
  hide3DS: false,
  gsmNumber: "",
  email: "email@email.com",
  checkConsumerDetail: {},
  subscriptionPaymentEnabled: false,
  ucsEnabled: false,
  fingerprintEnabled: false,
  payWithIyzicoFirstTab: false,
  metadata: {},
  createTag: function() {
    var iyziJSTag = document.createElement("script");
    iyziJSTag.setAttribute(
      "src",
      "https://sandbox-static.iyzipay.com/checkoutform/v2/bundle.js?v=1634688058781"
    );
    document.head.appendChild(iyziJSTag);
  },
};
iyziInit.createTag();

This code, creates a whole payment form inside <div id="iyzipay-checkout-form"></div>.

I can’t just have it as normal react code, because it is coming from the api of payment gateway provider. This script needs to run and directly add those elements to the dom.

Here is the problem:

If I paste this code into the console of the browser, it runs, adds script tags to head of document, which then creates my form inside of the div. And I can see the form.

However, if I put this code inside my react app, it runs, adds the script tags to head of the document, then nothing happens. The form is not created, my div with id of “iyzipay-checkout-form” is empty.

Why? I’m losing my mind, can’t figure this out for 2 days.

Should mention this too: If I create a standalone index.html, put this code in script tag on head of the document, and then just add a div with id of “iyzipay-checkout-form”, this does create the form on that html page. So that code only doesn’t work inside react.

You can test this on React Playground: https://codesandbox.io/s/react-playground-forked-4ht85

On the page you see, you won’t see the form even tho there’s the code to create it, but if you open the console of the playground, and paste the same “that code” i’ve given on top of this question, the form will appear. You can right click inspect too, to see the head tag and the stuff created inside it.

Answer

So the issue is that the script that’s injected by iyziInit.createTag(); expects the iyziInit variable to be defined in the global scope (attached to window).

Here’s an example below that works and shows the form.

import logo from "./logo.svg";
import "./App.css";

import { useEffect, useState } from "react";

function MyComp() {
  const [, setCalled] = useState(false);

  useEffect(() => {
    setCalled(called => {
      if (!called) {
        window.iyziInit = {
          currency: "TRY",
          token: "23bfa27a-172a-493d-b42f-8b091589eaa0",
          price: 2.4,
          locale: "tr",
          baseUrl: "https://sandbox-api.iyzipay.com",
          merchantGatewayBaseUrl: "https://sandbox-merchantgw.iyzipay.com",
          registerCardEnabled: true,
          bkmEnabled: true,
          bankTransferEnabled: false,
          bankTransferRedirectUrl: "https://localhost:3000/callback",
          bankTransferCustomUIProps: {},
          campaignEnabled: false,
          creditCardEnabled: true,
          bankTransferAccounts: [],
          userCards: [],
          fundEnabled: true,
          memberCheckoutOtpData: {},
          force3Ds: false,
          isSandbox: true,
          storeNewCardEnabled: true,
          paymentWithNewCardEnabled: true,
          enabledApmTypes: ["SOFORT", "IDEAL", "QIWI", "GIROPAY"],
          payWithIyzicoUsed: false,
          payWithIyzicoEnabled: true,
          payWithIyzicoCustomUI: {},
          buyerName: "John",
          buyerSurname: "Doe",
          merchantInfo: "",
          cancelUrl: "",
          buyerProtectionEnabled: false,
          hide3DS: false,
          gsmNumber: "",
          email: "email@email.com",
          checkConsumerDetail: {},
          subscriptionPaymentEnabled: false,
          ucsEnabled: false,
          fingerprintEnabled: false,
          payWithIyzicoFirstTab: false,
          metadata: {},
          createTag: function() {
            var iyziJSTag = document.createElement("script");
            iyziJSTag.setAttribute(
              "src",
              "https://sandbox-static.iyzipay.com/checkoutform/v2/bundle.js?v=1634688058781"
            );
            document.head.appendChild(iyziJSTag);
          }
        };
        window.iyziInit.createTag();
        return true;
      }
    });

    return () => delete window.iyziInit;
  }, []);

  return <></>;
}

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
      <MyComp />
    </div>
  );
}

export default App;