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

React/Next.js组件挂载时无法重新加载外部脚本问题求助

问题原因与解决方案

核心原因

  1. 浏览器缓存拦截:相同URL的脚本被浏览器缓存,后续加载时直接读取缓存副本,不会重新解析执行。
  2. 脚本全局状态锁定:Greenhouse的求职板脚本首次执行后,会在全局环境创建标识变量(如window.grnhse)或保留已生成的DOM结构,再次加载时检测到这些存在就跳过初始化流程。
  3. 代码清理不彻底:当前的清理函数仅移除script标签,未清除脚本生成的全局变量和残留DOM,导致脚本重新加载时误以为已完成初始化。

实现挂载时重新运行脚本的方案

1. 破除浏览器缓存

在脚本URL后追加唯一时间戳,让浏览器认为是全新资源,强制重新请求并执行:

script.src = `https://boards.greenhouse.io/embed/job_board/js?for=company&t=${Date.now()}`;

2. 彻底清理脚本残留状态

组件卸载时,除了移除script标签,还要清空目标容器并删除脚本创建的全局变量:

return () => {
  // 移除脚本标签
  if (script.parentNode) script.parentNode.removeChild(script);
  // 清空容器内所有内容
  grnhseAppDiv.innerHTML = "";
  // 清理Greenhouse全局状态(根据实际全局变量调整)
  if (window.grnhse) {
    delete window.grnhse;
  }
};

3. 调整useEffect依赖触发时机

将useEffect的依赖数组设置为组件的props(如[script1, script2]),确保props变化或组件重新挂载时,都会触发脚本的重新加载逻辑。

完整修改代码

"use client";
import { useEffect } from "react";
import { Container } from "@/components/layout/container";

interface JobOpeningsProps {
  script1: string;
  script2: string;
}

export const JobOpenings = ({ script1, script2 }: JobOpeningsProps) => {
  useEffect(() => {
    const grnhseAppDiv = document.getElementById("script");
    if (!grnhseAppDiv) return;

    // 清空容器,移除所有残留内容
    grnhseAppDiv.innerHTML = "";
    // 创建脚本需要的目标容器
    const grnhse_app = document.createElement("div");
    grnhse_app.id = "grnhse_app";
    grnhseAppDiv.appendChild(grnhse_app);

    // 创建带时间戳的脚本,强制浏览器重新请求
    const script = document.createElement("script");
    script.src = `https://boards.greenhouse.io/embed/job_board/js?for=company&t=${Date.now()}`;
    script.async = true;
    script.onload = () => {
      console.log("Script loaded successfully");
    };
    script.onerror = (error) => {
      console.error("Error loading script:", error);
    };

    grnhseAppDiv.appendChild(script);

    // 清理函数:卸载时移除脚本、清空容器、清理全局状态
    return () => {
      if (script.parentNode) script.parentNode.removeChild(script);
      grnhseAppDiv.innerHTML = "";
      if (window.grnhse) delete window.grnhse;
      console.log("Script state cleared");
    };
  }, [script1, script2]); // 依赖props,确保挂载/更新时触发

  return (
    <>
      <section className="h-full min-h-[40rem] rounded-card bg-primary">
        <Container>
          <article>
            <div id="script"></div>
          </article>
        </Container>
      </section>
    </>
  );
};

关于Next.js Script组件的说明

Next.js的Script组件默认会做缓存优化,相同URL只会执行一次。若要使用该组件实现重复加载,同样需要追加时间戳参数,且需手动在组件卸载时清理全局状态,但灵活性不如手动创建脚本标签的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:33:26