
在 react 应用中,使用 usescript 等自定义 hook 动态注入外部脚本时,若脚本路径采用相对形式(如 ./tagging.js),在标准路由下可能正常工作,但在动态路由(如 /brand/:brandname)下会因浏览器解析基准 url 变化而导致脚本加载失败,并抛出 "unexpected token '
理解 React 应用中的脚本动态注入
在现代 React 应用中,我们有时需要动态加载第三方脚本,例如分析工具、广告标签或自定义功能库。为了更好地管理脚本的生命周期和状态,通常会封装一个自定义 Hook,如 useScript。这个 Hook 负责创建、插入
以下是一个典型的 useScript Hook 实现:
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
const useScript = (url) => {
const [status, setStatus] = useState(url ? 'loading' : 'idle');
const location = useLocation(); // 引入 useLocation 以监听路由变化
useEffect(() => {
if (!url) {
setStatus('idle');
return;
}
// 尝试查找已存在的脚本,避免重复加载
let script = document.querySelector(`script[src="${url}"]`);
if (!script) {
// 如果脚本不存在,则创建并插入
script = document.createElement('script');
script.src = url;
script.type = 'text/javascript';
script.async = true;
document.head.appendChild(script);
// 首次设置 data-status 属性
const setAttributeFromEvent = (event) => {
script.setAttribute(
'data-status',
event.type === 'load' ? 'ready' : 'error'
);
};
script.addEventListener('load', setAttributeFromEvent);
script.addEventListener('error', setAttributeFromEvent);
} else {
// 如果脚本已存在,则读取其状态
setStatus(script.getAttribute('data-status'));
}
// 监听脚本加载状态,更新组件的 state
const setStateFromEvent = (event) => {
setStatus(event.type === 'load' ? 'ready' : 'error');
};
script.addEventListener('load', setStateFromEvent);
script.addEventListener('error', setStateFromEvent);
// 清理函数:组件卸载或 URL 变化时移除事件监听器
return () => {
if (script) {
script.removeEventListener('load', setStateFromEvent);
script.removeEventListener('error', setStateFromEvent);
}
};
}, [url, location]); // 依赖项包括 url 和 location
return status;
};
export default useScript;在组件中使用时,通常会这样调用:
const status = useScript('./tagging.js'); // 使用相对路径
console.log(status);动态路由下的脚本加载问题
当 React 应用使用 react-router-dom 配置了动态路由时,例如:
} /> } /> } /> } />
如果我们在 /offer 这样的标准路由下调用 useScript('./tagging.js'),脚本通常能正常加载。然而,当导航到 /hearing-agency/brand/phonak 这样的动态路由时,尽管 useScript Hook 可能报告脚本状态为 ready,但实际上脚本并未正确执行,并且在控制台会抛出 SyntaxError: Unexpected token '
检查文档的
部分,会发现











