React组件中TradingView Widget重复显示问题求助
解决TradingView Widget在React中重复显示的问题
问题现象
在React项目中通过自定义TradingViewWidget组件嵌入TradingView图表时,页面出现两个完全相同的Widget实例,已确认组件未触发重渲染,但重复问题依然存在。

原因分析
- TradingView的嵌入脚本会自动扫描页面中所有带有
tradingview-widget-container__widget类名的元素,并在每个匹配元素中渲染图表组件。你在组件的JSX中手动添加了该类名的div,同时脚本挂载的容器也会被自动注入图表结构,导致两个实例同时渲染。 - 组件的
useEffect没有清理逻辑,当组件卸载后重新挂载(比如路由切换),会重复创建脚本标签,进一步加剧重复渲染问题。
解决方案
- 移除JSX中手动编写的
tradingview-widget-container__widget元素,脚本会自动在挂载容器内生成所需DOM - 在
useEffect中添加清理函数,组件卸载时移除创建的脚本标签,避免残留 - 利用
useRef标记脚本是否已添加,确保脚本只被创建一次
修改后的代码示例
TradingViewWidget.jsx
import React, { useEffect, useRef, memo } from "react"; function TradingViewWidget() { const container = useRef(); const scriptAdded = useRef(false); // 标记脚本是否已添加 useEffect(() => { // 避免重复添加脚本 if (scriptAdded.current) return; const script = document.createElement("script"); script.src = "https://s3.tradingview.com/external-embedding/embed-widget-symbol-overview.js"; script.type = "text/javascript"; script.async = true; script.innerHTML = ` { "symbols": [ [ "BITSTAMP:BTCUSD|7D" ] ], "chartOnly": false, "width": "100%", "height": "100%", "locale": "en", "colorTheme": "light", "autosize": true, "showVolume": false, "showMA": false, "hideDateRanges": false, "hideMarketStatus": true, "hideSymbolLogo": false, "scalePosition": "left", "scaleMode": "Normal", "fontFamily": "Arial, sans-serif", "fontSize": "10", "noTimeScale": false, "valuesTracking": "1", "changeMode": "price-and-percent", "chartType": "area", "maLineColor": "#2962FF", "maLineWidth": 1, "maLength": 9, "gridLineColor": "rgba(91, 156, 246, 0.14)", "lineWidth": 2, "lineType": 0, "dateRanges": [ "1d|3", "1w|1D", "1m|1D", "3m|1D", "6m|1D", "12m|1M", "all|12M" ], "lineColor": "rgba(91, 156, 246, 1)", "topColor": "rgba(187, 217, 251, 0.2)", "bottomColor": "rgba(255, 255, 255, 0.39)", "dateFormat": "dd MMM", "timeHoursFormat": "24-hours" }`; container.current.appendChild(script); scriptAdded.current = true; // 清理函数:组件卸载时移除脚本 return () => { if (scriptAdded.current && container.current.contains(script)) { container.current.removeChild(script); scriptAdded.current = false; } }; }, []); return ( <div className="tradingview-widget-container flex justify-center mx-auto mt-5 lg:mt-0 border-4 border-red-500 min-w-96 h-96 md:w-5/6 md:h-3/4 lg:w-4/5 lg:h-[45rem]" ref={container}> <div className="tradingview-widget-copyright"> <a href="https://www.tradingview.com/" rel="noopener nofollow" target="_blank" > <span className="blue-text">Track all markets on TradingView</span> </a> </div> </div> ); } export default memo(TradingViewWidget);
关键修改点
- 移除了JSX中手动添加的
<div className="tradingview-widget-container__widget"></div>,避免脚本重复渲染 - 添加
scriptAddedref标记脚本是否已创建,防止重复添加 - 在
useEffect的返回函数中实现清理逻辑,组件卸载时移除创建的脚本标签
内容的提问来源于stack exchange,提问作者CompiledWithErrors
相关产品推荐
相关产品推荐

