Next.js Discord

Discord Forum

Script delay to load

Unanswered
Gabriel Moresco posted this in #help-forum
Open in Discord
Hello guys, I have a script inside my NextJS 14 app, that render a form from my CRM (Bitrix24).

### bitrix-establishment-form.js
;(function (w, d, u) {
  const s = d.createElement('script')
  s.async = true
  s.src = u + '?' + ((Date.now() / 180000) | 0)
  const h = d.getElementsByTagName('script')[0]
  h.parentNode.insertBefore(s, h)
})(window, document, 'https://cdn.bitrix24.com.br/{{SCRIPT_ID}}/crm/form/loader_14.js')


The only way I found to work is this:

### EstablishmentForm.tsx
'use client'

import { useEffect } from 'react'

export const EstablishmentForm = () => {
  useEffect(() => {
    const scriptId = '/scripts/bitrix-establishment-form.js'

    if (document.getElementById(scriptId) != null) {
      return
    }

    const script = document.createElement('script')
    script.id = scriptId
    script.src = scriptId
    script.setAttributeNS(null, 'data-b24-form', 'inline/{{ID}}/{{ID}}')
    script.setAttributeNS(null, 'data-skip-moving', 'true')
    script.defer = true

    const scriptDiv = document.getElementById('script_div')

    scriptDiv?.appendChild(script)

    return () => {
      scriptDiv?.removeChild(script)
    }
  }, [])

  return <div id='script_div' className='w-full' />
}


I put the EstablishmentForm component inside a div. But there is a problem, the form only renders a few seconds after the page finishes loading.

I tried to use Next Script:

<Script
  src='/scripts/bitrix-establishment-form.js'
  data-b24-form='inline/14/vle4l0'
  data-skip-moving='true'
/>


But another problem arises, the form is rendered in the end of the body, after everything in the page, but I read that this is the expected behavior (I think).

I tried to use the strategy='beforeInteractive'. The <script> is loaded in the <head> of the app, but the form is not rendered on the screen.

Could you help me to make this work, the form render when the page load?

20 Replies

Cape lion
I have the same problem
Up
up
up
Toyger
you need to check does your form have some distinguishable id
then add some id to div where you want to place it
bitrix24 have custom form event on init you can use it in use effect
  useEffect(() => {
    const handleFormInit = () => {
      const targetDiv = document.getElementById("your_target_div_id");
      const formDiv = document.getElementById("your_FORM_div_id");
      if (formDiv && targetDiv) {
        targetDiv.appendChild(formDiv);
      }
    };

    window.addEventListener('b24:form:init', handleFormInit);

    return () => {
      window.removeEventListener('b24:form:init', handleFormInit);
    };
  }, []);
'use client'

export const EstablishmentForm = () => {
  return (
    <>
      <script
        src='/scripts/bitrix-establishment-form.js'
        data-b24-form='inline/14/vle4l0'
        data-skip-moving='true'
        defer
        onLoad={() => {
          const formContainer = document.getElementById('establishment-form-container')
          const form = document.getElementsByClassName('b24-form')[0]

          if (formContainer && form) {
            formContainer.appendChild(form)
          }
        }}
      />
      <div id='establishment-form-container' className='flex flex-1' />
    </>
  )
}
it worked, but the form is rendered after the page load
@Gabriel Moresco it worked, but the form is rendered after the page load
Toyger
it's external script, so it basically impossible to load it with your page.
theoretically you can add it directly to layout for your page, but even if it will work, it will be only for direct page open, if you redirect with user with client side rendering it will probably ignore layout file.
@Ray is it possible to share the script so I can try?
Yes, i created a repo for it
i created 3 components, that is the three ways i tried to work
@Gabriel Moresco i created 3 components, that is the three ways i tried to work
try this
"use client";

import { ComponentRef, useEffect, useRef } from "react";

export default function Page() {
  const formref = useRef<ComponentRef<"div">>(null);

  useEffect(() => {
    if (formref.current) {
      const script = document.createElement("script");
      script.id = "b24form";
      script.innerHTML = `(function (w, d, u) {
            const s = d.createElement("script");
            s.async = true;
            s.src = u + "?" + ((Date.now() / 180000) | 0);
            const h = d.getElementsByTagName("script")[0];
            h.parentNode.insertBefore(s, h);
        })(
            window,
            document,
            "https://cdn.bitrix24.com.br/b25948707/crm/form/loader_14.js"
            );`;
      script.setAttributeNS(null, "data-b24-form", "inline/14/vle4l0");
      script.setAttributeNS(null, "data-skip-moving", "true");
      script.defer = true;

      formref.current.appendChild(script);

      return () => {
        document.getElementById("b24form")?.remove();
      };
    }
  }, []);

  return (
    <div className="grid grid-cols-2">
      <div className="flex justify-center items-center">1</div>
      <div ref={formref} className="min-h-[500px]"></div>
    </div>
  );
}
@Gabriel Moresco I tried, but the form still render after the page load
it has to be loaded after the page load because the form is loaded from a javascript script
otherwise, you would have to make the form yourself and make a POST request to their endpoint when the form is submitted