You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useScript加载Bookeo组件部分浏览器无法渲染iframe问题

React动态加载Bookeo组件的浏览器兼容问题解决方案

问题分析

你当前用useScript钩子动态加载Bookeo组件时,出现Chrome(部分系统)、Edge浏览器无法渲染iframe的情况,但直接在index.html中添加script标签却能正常工作,核心原因在于:

  • 动态脚本的执行时机与React组件的DOM渲染周期不同步,当脚本执行时,目标挂载容器可能还未完全插入DOM
  • 直接加到body的脚本,无法让Bookeo widget精准定位到你指定的Grid容器,不同浏览器对DOM节点就绪的判断逻辑存在差异,导致渲染失败

解决方案1:指定挂载容器并同步脚本加载时机

修改useScript钩子,让脚本挂载到目标容器,并确保容器就绪后再加载脚本:

import { useEffect, useRef } from 'react';

const useScript = (url, containerRef) => {
  useEffect(() => {
    const targetElement = containerRef.current;
    if (!targetElement) return;

    // 避免重复加载脚本
    const existingScript = targetElement.querySelector(`script[src="${url}"]`);
    if (existingScript) return;

    const script = document.createElement('script');
    script.src = url;
    script.async = true;
    // 通过URL参数告诉Bookeo要挂载到哪个容器(参考Bookeo文档,部分widget支持container参数)
    script.src += `&container=${targetElement.id}`;

    targetElement.appendChild(script);

    return () => {
      if (script.parentNode) {
        script.parentNode.removeChild(script);
      }
    };
  }, [url, containerRef]);
};

// 组件内使用
const BookeoContainer = () => {
  const containerRef = useRef(null);
  
  return (
    <Grid item xs={12} ref={containerRef} id="bookeo-widget-container">
      {useScript("https://bookeo.com/widget.js?a=***************", containerRef)}
    </Grid>
  );
};

解决方案2:手动控制widget初始化(更可靠)

如果Bookeo提供了全局初始化API,直接封装成组件,精准控制初始化时机:

import { useEffect, useRef } from 'react';

const BookeoWidget = ({ accountId }) => {
  const containerRef = useRef(null);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    // 检查脚本是否已加载
    let scriptLoaded = !!document.querySelector('script[src*="bookeo.com/widget.js"]');
    const initWidget = () => {
      // 调用Bookeo全局初始化方法(需参考官方文档确认API)
      if (window.Bookeo?.init) {
        window.Bookeo.init({
          container: container.id,
          accountId: accountId
        });
      }
    };

    if (scriptLoaded) {
      initWidget();
      return;
    }

    // 加载脚本并绑定加载完成事件
    const script = document.createElement('script');
    script.src = `https://bookeo.com/widget.js?a=${accountId}`;
    script.async = true;
    script.onload = initWidget;
    script.onerror = () => console.error('Bookeo脚本加载失败');

    document.body.appendChild(script);

    // 组件卸载时清理
    return () => {
      if (window.Bookeo?.destroy) {
        window.Bookeo.destroy(container.id);
      }
      script.parentNode?.removeChild(script);
    };
  }, [accountId]);

  return <Grid item xs={12} ref={containerRef} id="bookeo-widget-container" />;
};

// 使用示例
<BookeoWidget accountId="***************" />

额外优化点

  • 用useLayoutEffect替代useEffect:如果依然存在时机问题,useLayoutEffect会在DOM更新后同步执行,比异步的useEffect更适合确保容器就绪
  • 添加加载状态:在组件中加入loading提示,提升用户体验

内容的提问来源于stack exchange,提问作者Cem Adatepe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:03:22