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

切换React页面后外部JavaScript脚本无法运行求助

问题分析

当前问题的核心在于:

  • 组件卸载时useScript的清理函数会移除脚本,但浏览器会缓存该脚本,再次挂载组件时脚本不会重新执行,导致dw相关的初始化逻辑无法触发。
  • 配置dw的useEffect依赖为空数组,仅在组件首次挂载时执行,二次挂载时不会重新调用dw('settings')和dw('onPageChange')。
  • 脚本加载与dw调用的时机不匹配,可能出现dw调用时脚本尚未加载完成(二次挂载时)。
解决方案

1. 优化useScript Hook,跟踪脚本加载状态

修改useScript,让它返回脚本的加载状态,避免重复创建/移除脚本,同时确保脚本加载完成后再执行后续逻辑:

const useScript = (url) => {
  const [loaded, setLoaded] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    // 检查脚本是否已存在于页面中
    const existingScript = document.querySelector(`script[src="${url}"]`);
    
    if (existingScript) {
      // 如果脚本已存在,直接标记为加载完成
      setLoaded(true);
      return;
    }

    const script = document.createElement('script');
    script.src = url;
    script.async = true;

    const handleLoad = () => setLoaded(true);
    const handleError = (err) => setError(err);

    script.addEventListener('load', handleLoad);
    script.addEventListener('error', handleError);

    document.body.appendChild(script);

    return () => {
      script.removeEventListener('load', handleLoad);
      script.removeEventListener('error', handleError);
      // 不要移除脚本,避免二次加载时缓存问题;若必须移除,需同时清理window.dw
      // document.body.removeChild(script);
      // delete window.dw;
      // delete window.dw.q;
    };
  }, [url]);

  return { loaded, error };
};

2. 调整Events组件,确保每次挂载都重新初始化dw

修改Events组件的useEffect,移除空依赖,改为在组件挂载且脚本加载完成后执行dw的配置逻辑:

function Events() {
  const { t } = useTranslation();
  const { loaded } = useScript('https://resc.deskline.net/DW5/start/TERRBRENTA/api_code/index.js');

  useEffect(() => {
    if (!loaded) return;

    // 每次挂载都重新初始化dw队列
    window.dw = window.dw || function () { (window.dw.q = window.dw.q || []).push(arguments) };
    window.dw('settings', api_code,
    {
      "context": {"targetRoute":["/eventi","/events","/veranstaltungen"]},
      "lang": document.cookie.split('; ').find((row) => row.startsWith('i18next='))?.split('=')[1],
      "target": "tosc5container",
      "loadingAnimationColor": {
        "main": '#999999',
        "alt": '#B9E0AF'
      }
    });
    window.dw('onPageChange', api_code);

    // 组件卸载时清空容器内容,避免残留
    return () => {
      const container = document.getElementById('tosc5container');
      if (container) container.innerHTML = '';
      // 若需要完全重置dw,可添加:
      // window.dw.q = [];
    };
  }, [loaded, api_code]); // 依赖添加loaded和api_code,确保状态变化时重新执行

  return (
    <section className="container pt-6 pb-6">
      <Helmet>
        <title>{t('navbar.events')}</title>
        <meta  name="description" content={t('pageDesc.events')} />   
      </Helmet>
      
      <h1 className="pb-2">{t('navbar.events')}</h1>
      <p className="pb-2">{t('evt')}</p>
      
      <div id="tosc5container" style={{ minHeight: "250px" }} />
    </section>
  );
}

3. 额外优化:确保路由切换时的容器状态

由于React路由切换是SPA模式,组件卸载时容器#tosc5container的内容可能残留,导致二次挂载时脚本无法正确渲染,因此在组件卸载时清空容器内容(已包含在上述useEffect的清理函数中)。

关键说明
  • 保留脚本在页面中不删除,利用浏览器缓存避免重复加载,同时确保二次挂载时脚本已存在,只需重新调用dw的初始化逻辑即可。
  • 将loaded作为useEffect的依赖,确保只有脚本加载完成后才执行dw的配置,避免调用时机过早。
  • 每次组件挂载都重新执行dw的配置和onPageChange,确保容器能正确渲染内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:40:33