59 lines
1.6 KiB
JavaScript
59 lines
1.6 KiB
JavaScript
import { useEffect, useRef } from 'react'
|
|
|
|
export default function useLayoutInit() {
|
|
const initialized = useRef(false)
|
|
|
|
useEffect(() => {
|
|
// Dual guard: useRef + window.__rakarInit
|
|
// useRef protects against re-renders in same mount cycle
|
|
// window.__rakarInit protects against React 19 strict mode
|
|
// unmount/remount cycle where useRef may be reset
|
|
if (initialized.current) return
|
|
initialized.current = true
|
|
if (window.__rakarInit) return
|
|
let destroyed = false
|
|
let rafId = null
|
|
|
|
function tryInit() {
|
|
if (destroyed) return false
|
|
if (typeof window.rakar_content_load_scripts === 'function') {
|
|
if (!window.__rakarInit) {
|
|
window.__rakarInit = true
|
|
window.rakar_content_load_scripts()
|
|
}
|
|
window.__layoutReady = true
|
|
window.dispatchEvent(new Event('layout-ready'))
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Immediate attempt
|
|
if (tryInit()) return
|
|
|
|
// Poll with requestAnimationFrame for efficiency
|
|
function poll() {
|
|
if (!destroyed && !tryInit()) {
|
|
rafId = requestAnimationFrame(poll)
|
|
}
|
|
}
|
|
rafId = requestAnimationFrame(poll)
|
|
|
|
// Fallback timeout (3 seconds)
|
|
const fallback = setTimeout(() => {
|
|
if (!destroyed) {
|
|
window.__layoutReady = true
|
|
window.dispatchEvent(new Event('layout-ready'))
|
|
destroyed = true
|
|
if (rafId) cancelAnimationFrame(rafId)
|
|
}
|
|
}, 3000)
|
|
|
|
return () => {
|
|
destroyed = true
|
|
if (rafId) cancelAnimationFrame(rafId)
|
|
clearTimeout(fallback)
|
|
}
|
|
}, [])
|
|
}
|