React中使用google_translate_element脚本报错及解决方案咨询
解决方案
这个错误的核心原因是:动态加载谷歌翻译脚本时,页面切换到后台(标签页切换/切出浏览器)会导致谷歌翻译的内部逻辑试图访问已失效的DOM引用或未初始化的全局变量,而直接在index.html引入脚本时,全局状态加载更稳定,不会出现这类问题。以下是几种可行的解决办法:
方案1:添加完整的清理与页面可见性监听逻辑
通过保存翻译实例引用,在页面切换时销毁/重建实例,同时在组件卸载时清理所有相关资源:
import { useEffect, useRef } from 'react'; function GoogleTranslate() { const translateContainerRef = useRef(null); const translateInstanceRef = useRef(null); useEffect(() => { // 初始化翻译控件 function googleTranslateElementInit() { if (window.google?.translate) { translateInstanceRef.current = new window.google.translate.TranslateElement( { pageLanguage: 'zh' }, translateContainerRef.current ); } } // 动态加载脚本 const translateScript = document.createElement("script"); translateScript.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"; document.body.appendChild(translateScript); window.googleTranslateElementInit = googleTranslateElementInit; // 监听页面可见性变化,切换后台时销毁实例,前台时重建 function handleVisibilityChange() { if (document.hidden) { translateInstanceRef.current?.destroy?.(); translateInstanceRef.current = null; } else if (window.google?.translate && !translateInstanceRef.current) { translateInstanceRef.current = new window.google.translate.TranslateElement( { pageLanguage: 'zh' }, translateContainerRef.current ); } } document.addEventListener('visibilitychange', handleVisibilityChange); // 组件卸载时清理所有资源 return () => { document.removeEventListener('visibilitychange', handleVisibilityChange); translateInstanceRef.current?.destroy?.(); document.body.removeChild(translateScript); delete window.googleTranslateElementInit; // 清理谷歌翻译生成的DOM元素 document.querySelectorAll('.goog-te-banner-frame, .goog-te-menu-frame').forEach(el => el.remove()); document.body.classList.remove('translated-ltr'); }; }, []); return <div ref={translateContainerRef} id="google_translate_element"></div>; } export default GoogleTranslate;
方案2:用React Helmet模拟index.html引入脚本的效果
借助react-helmet组件将脚本插入到页面<head>中,和直接在index.html引入的加载逻辑一致,避免动态加载的时序问题:
import { Helmet } from 'react-helmet'; import { useEffect, useRef } from 'react'; function GoogleTranslate() { const translateContainerRef = useRef(null); useEffect(() => { function googleTranslateElementInit() { if (window.google?.translate) { new window.google.translate.TranslateElement( { pageLanguage: 'zh' }, translateContainerRef.current ); } } window.googleTranslateElementInit = googleTranslateElementInit; return () => { delete window.googleTranslateElementInit; // 清理残留的翻译DOM document.querySelectorAll('.goog-te-banner-frame, .goog-te-menu-frame').forEach(el => el.remove()); document.body.classList.remove('translated-ltr'); }; }, []); return ( <> <Helmet> <script src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" async defer></script> </Helmet> <div ref={translateContainerRef} id="google_translate_element"></div> </> ); }
方案3:增强初始化的健壮性
通过延迟重试机制确保谷歌翻译的全局对象加载完成,同时在页面回到前台时检查控件状态:
import { useEffect } from 'react'; function GoogleTranslate() { useEffect(() => { function googleTranslateElementInit() { // 检查谷歌翻译对象是否存在,不存在则延迟重试 if (!window.google || !window.google.translate) { setTimeout(googleTranslateElementInit, 500); return; } new window.google.translate.TranslateElement( { pageLanguage: 'zh' }, 'google_translate_element' ); } const translateScript = document.createElement("script"); translateScript.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"; document.body.appendChild(translateScript); window.googleTranslateElementInit = googleTranslateElementInit; // 页面回到前台时,检查控件是否存在,不存在则重新初始化 function handleVisibilityChange() { if (!document.hidden) { const translateControl = document.querySelector('.goog-te-combo'); if (!translateControl && window.google?.translate) { googleTranslateElementInit(); } } } document.addEventListener('visibilitychange', handleVisibilityChange); return () => { document.removeEventListener('visibilitychange', handleVisibilityChange); document.body.removeChild(translateScript); delete window.googleTranslateElementInit; }; }, []); return <div id="google_translate_element"></div>; }
内容的提问来源于stack exchange,提问作者AMAL C K
相关产品推荐
相关产品推荐

