Skip to main content
Get Started
Documentation

React <iframe> component

During the lifecycle of the embed, Tractorscope embedded dashboards will fire messages indicating the latest state of loading. Within the following example, you will see dynamic height, width and loading state updates to be handled from the event listener within the embedded iframe URL.
import { useEffect, useState, useMemo } from 'react'

export default function TractorReport({
  url,
  width: incomingWidth,
  height: incomingHeight,
  dashboard,
  isLoading = false,
}) {
  const [messageLoading, setMessageLoading] = useState < boolean > true
  const [iframeLoading, setIframeLoading] = useState < boolean > true
  const [width, setWidth] = useState(incomingWidth || '100%')
  const [height, setHeight] = useState(incomingHeight || '100px')

  useEffect(() => {
    if (url) {
      setMessageLoading(true)
      setIframeLoading(true)
    }
  }, [url])

  useEffect(() => {
    // listen for iframe messages telling us when report has loaded and with what dimensions
    function handleMessage(event) {
      if (event?.data?.dashboardId && event?.data?.dashboardId === dashboard) {
        if (height !== '100%') setHeight(event.data.height + 'px')
        if (width !== '100%') setWidth(event.data.width + 'px')
      }
      setTimeout(() => setMessageLoading(false), 2000)
    }

    window.addEventListener('message', handleMessage)

    return () => {
      window.removeEventListener('message', handleMessage)
    }
  }, [])

  function iframeLoaded() {
    setTimeout(() => setIframeLoading(false), 100)
  }

  const showLoader = useMemo(
    () => messageLoading || isLoading || iframeLoading,
    [messageLoading, isLoading, iframeLoading]
  )

  const opacity = showLoader ? 0 : 1

  return (
    <div>
      {showLoader && (
        <div
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            width,
            height,
          }}
        >
          Loading...
        </div>
      )}
      <div style={{ opacity }}>
        <iframe
          title="Report"
          src={url}
          style={{ width, height, border: 'none' }}
          scrolling="no"
          onLoad={iframeLoaded}
        />
      </div>
    </div>
  )
}
import { useEffect, useState, useMemo } from 'react'

export default function TractorReport({
  url,
  width: incomingWidth,
  height: incomingHeight,
  dashboard,
  isLoading = false,
}) {
  const [messageLoading, setMessageLoading] = useState < boolean > true
  const [iframeLoading, setIframeLoading] = useState < boolean > true
  const [width, setWidth] = useState(incomingWidth || '100%')
  const [height, setHeight] = useState(incomingHeight || '100px')

  useEffect(() => {
    if (url) {
      setMessageLoading(true)
      setIframeLoading(true)
    }
  }, [url])

  useEffect(() => {
    // listen for iframe messages telling us when report has loaded and with what dimensions
    function handleMessage(event) {
      if (event?.data?.dashboardId && event?.data?.dashboardId === dashboard) {
        if (height !== '100%') setHeight(event.data.height + 'px')
        if (width !== '100%') setWidth(event.data.width + 'px')
      }
      setTimeout(() => setMessageLoading(false), 2000)
    }

    window.addEventListener('message', handleMessage)

    return () => {
      window.removeEventListener('message', handleMessage)
    }
  }, [])

  function iframeLoaded() {
    setTimeout(() => setIframeLoading(false), 100)
  }

  const showLoader = useMemo(
    () => messageLoading || isLoading || iframeLoading,
    [messageLoading, isLoading, iframeLoading]
  )

  const opacity = showLoader ? 0 : 1

  return (
    <div>
      {showLoader && (
        <div
          style={{
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            width,
            height,
          }}
        >
          Loading...
        </div>
      )}
      <div style={{ opacity }}>
        <iframe
          title="Report"
          src={url}
          style={{ width, height, border: 'none' }}
          scrolling="no"
          onLoad={iframeLoaded}
        />
      </div>
    </div>
  )
}
Happy react embeds!