Next.js中切换语言后重新初始化第三方脚本的方案
解决Next.js 13无刷新切换语言时在线客服聊天按钮不更新的问题
核心问题原因
Next.js 的 Script 组件会根据 id 缓存脚本执行状态,只要 id 不变,即使传入的脚本内容变化,也不会重新执行。同时切换语言后,旧的在线客服实例和DOM残留会干扰新实例初始化。
解决方案:手动控制脚本加载与清理
放弃依赖 next/script,改用 useEffect 监听 codePlan 变化,手动完成旧实例清理、新脚本初始化的流程:
import { useEffect, useRef } from 'react'; export default function OnlineHelpButton({ codePlan }) { const containerRef = useRef(null); useEffect(() => { // 1. 清理旧的聊天组件与全局状态 if (containerRef.current) { containerRef.current.innerHTML = ''; } // 重置全局OnlineHelpAPI状态,避免旧数据干扰 if (window.OnlineHelpAPI) { window.OnlineHelpAPI.chat_buttons = []; window.OnlineHelpAPI.loaded = false; } else { window.OnlineHelpAPI = {}; } // 2. 重新初始化在线客服 const initChat = () => { const OnlineHelpAPI = window.OnlineHelpAPI; (function(t) { function loadScript(baseUrl) { const script = document.createElement('script'); const firstScript = document.getElementsByTagName('script')[0]; script.type = 'text/javascript'; script.async = true; script.src = `${baseUrl}${t.site_id}`; // 给脚本打标识,方便后续清理 script.dataset.chatCodePlan = codePlan; script.onload = () => { t.loaded = true; }; firstScript.parentNode.insertBefore(script, firstScript); } t.chat_buttons.push({ code_plan: codePlan, div_id: containerRef.current.id }); t.site_id = 60003785; t.main_code_plan = codePlan; loadScript('https://vue.livehelp100service.com/livechat.ashx?siteId='); setTimeout(() => { if (!t.loaded) { loadScript('https://vue.livehelp100servicestandby.com/livechat.ashx?siteId='); } }, 5000); })(OnlineHelpAPI); }; initChat(); // 3. 清理函数:组件卸载或codePlan变更时移除旧脚本 return () => { const oldScripts = document.querySelectorAll(`script[data-chat-code-plan="${codePlan}"]`); oldScripts.forEach(script => script.remove()); if (containerRef.current) { containerRef.current.innerHTML = ''; } }; }, [codePlan]); // 监听codePlan变化,触发重新初始化 return ( <div ref={containerRef} id={`onlinehelp-button-${codePlan}`} /> ); }
关键细节说明
- 容器引用:用
useRef获取聊天按钮容器,方便直接操作DOM清空旧内容 - 全局状态重置:每次切换语言时重置
OnlineHelpAPI的聊天按钮列表和加载状态,确保新实例用最新的codePlan初始化 - 脚本标识:给动态创建的脚本添加
data-chat-code-plan属性,后续可以精准移除对应语言的旧脚本 - 清理函数:在
useEffect的返回函数中清理旧脚本和DOM,避免内存泄漏和残留元素干扰
内容的提问来源于stack exchange,提问作者piraha
相关产品推荐
相关产品推荐

