Next.js中如何用useEffect Hook仅渲染一次Google翻译组件
解决Google翻译按钮重复渲染问题
问题场景
仅在单个页面中使用以下Google翻译组件,却出现两个独立的翻译按钮实例:
import { useEffect } from "react"; const GoogleTranslate = () => { useEffect(() => { let addScript = document.createElement("script"); addScript.setAttribute( "src", "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" ); document.body.appendChild(addScript); window.googleTranslateElementInit = googleTranslateElementInit; }, []); const googleTranslateElementInit = () => { return new window.google.translate.TranslateElement( { pageLanguage: "en", layout: google.translate.TranslateElement.InlineLayout.BUTTON, }, "google_translate_element" ); }; return <div id="google_translate_element"></div>; }; export default GoogleTranslate;
问题原因
- 组件可能被重复挂载(比如路由切换时未正确卸载、父组件重复渲染导致该组件多次实例化)
- 每次组件挂载都会向页面添加Google翻译脚本,脚本加载完成后触发
googleTranslateElementInit,若全局函数被多次赋值,会重复创建翻译实例 - Google翻译脚本本身的缓存机制,会导致重复添加脚本时初始化逻辑多次执行
解决方法
通过添加判断逻辑,避免重复添加脚本和创建翻译实例,同时处理组件卸载时的副作用:
import { useEffect } from "react"; const GoogleTranslate = () => { useEffect(() => { // 前置检查:避免重复初始化 const hasTranslateScript = document.querySelector('script[src*="translate.google.com/translate_a/element.js"]'); const hasTranslateInstance = document.querySelector('#google_translate_element iframe'); if (hasTranslateScript || hasTranslateInstance) return; // 创建并添加翻译脚本 const addScript = document.createElement("script"); addScript.setAttribute( "src", "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" ); document.body.appendChild(addScript); // 定义全局初始化函数,完成后清理 window.googleTranslateElementInit = () => { new window.google.translate.TranslateElement( { pageLanguage: "en", layout: window.google.translate.TranslateElement.InlineLayout.BUTTON, }, "google_translate_element" ); delete window.googleTranslateElementInit; }; // 组件卸载时清理资源 return () => { if (addScript && addScript.parentNode) addScript.parentNode.removeChild(addScript); if (window.googleTranslateElementInit) delete window.googleTranslateElementInit; const translateContainer = document.getElementById('google_translate_element'); if (translateContainer) translateContainer.innerHTML = ''; }; }, []); return <div id="google_translate_element"></div>; }; export default GoogleTranslate;
关键修改点说明
- 前置检查:先判断页面是否已有翻译脚本或实例,存在则直接返回,避免重复执行初始化逻辑
- 清理全局函数:初始化完成后删除
window.googleTranslateElementInit,防止后续脚本加载时重复触发 - 卸载清理:组件卸载时移除脚本、删除全局函数、清空翻译容器,避免残留实例影响其他页面
内容的提问来源于stack exchange,提问作者Musiur Alam Opu
相关产品推荐
相关产品推荐

