React路由跳转后动态注入CDN脚本未生效,如何解决?
解决React路由跳转后动态加载CDN徽章不生效的问题
问题根源
页面刷新时,脚本与DOM元素同步加载,第三方CDN脚本会自动扫描页面DOM并完成徽章初始化;但路由跳转时,组件挂载后脚本才被注入(或之前已加载过),此时脚本不会主动重新扫描新渲染的DOM节点,导致徽章无法正常显示。另外原UseScript Hook存在重复注入脚本、卸载时移除脚本可能影响其他页面使用的问题。
解决方案
1. 优化UseScript Hook
修改Hook逻辑,避免重复加载脚本,同时支持脚本加载完成后的回调:
import { useEffect, useState } from "react"; const UseScript = (url, onLoad) => { const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { // 检查页面中是否已存在目标脚本 const existingScript = document.querySelector(`script[src="${url}"]`); if (existingScript) { // 脚本已加载,直接触发初始化回调 if (onLoad && !isLoaded) { onLoad(); setIsLoaded(true); } return; } const script = document.createElement("script"); script.src = url; script.async = true; // 脚本加载完成后执行回调 script.onload = () => { setIsLoaded(true); if (onLoad) onLoad(); }; document.body.appendChild(script); // 不再卸载脚本,避免影响其他页面的同脚本使用 return () => {}; }, [url, onLoad, isLoaded]); return isLoaded; }; export default UseScript;
2. 修改组件代码,手动触发徽章初始化
在组件中利用UseScript的回调,调用第三方脚本暴露的全局初始化方法,确保路由跳转后徽章能正常渲染:
import { useEffect } from "react"; import UseScript from "./UseScript"; // 路径根据实际项目调整 export default function PubItems({ id, title = "This is title", authors = "this is the author list", journaL = "this is the journal name", issue = "This is the issue number", date = "This is publication date", doi = "this is link", impact = "0.00", metric = "this is 000", plum = "", }) { // 加载Dimensions脚本并触发初始化 const isDimensionsLoaded = UseScript("https://badge.dimensions.ai/badge.js", () => { window.DimensionsBadges?.load(); }); // 加载PlumX脚本并触发初始化 const isPlumXLoaded = UseScript("//cdn.plu.mx/widget-popup.js", () => { window.plumx?.load(); }); // 组件挂载后,再次触发初始化(确保路由跳转时DOM已渲染完成) useEffect(() => { if (isDimensionsLoaded) window.DimensionsBadges?.load(); if (isPlumXLoaded) window.plumx?.load(); }, [isDimensionsLoaded, isPlumXLoaded]); return ( <PubItemsStyles> <div className="pubItems_info"> <h3> <a className="pubtitle" href={doi} target="_blank"> {title} </a> </h3> <p className="authors">{authors}</p> <p className="journal"> <span className="jName">{journaL}</span> <span className="jIssue">{issue}</span> <span className="jIssue">{impact}</span> </p> <p className="date">{date}</p> <div className="metrics"> <div> <a className="doi" href={doi} target="_blank"> Read Article </a> </div> <span> <a href={plum} target="_blank" rel="noopener noreferrer" className="plumx-plum-print-popup plum-bigben-theme" data-size="medium" data-popup="bottom" > plumx </a> </span> <span className="__dimensions_badge_embed__" data-doi={metric} data-style="large_rectangle" ></span> </div> </div> </PubItemsStyles> ); }
核心说明
- 避免重复加载:通过检查页面中已存在的脚本,防止路由跳转时重复注入相同脚本。
- 手动初始化:第三方徽章脚本通常会暴露全局初始化方法(如
DimensionsBadges.load()、plumx.load()),调用这些方法可强制脚本重新扫描DOM并渲染新徽章。 - 保留脚本:移除原Hook中卸载时删除脚本的逻辑,避免其他页面使用同脚本时被意外清除。
内容的提问来源于stack exchange,提问作者MD. Hasanur Rahman
相关产品推荐
相关产品推荐

