我正在尝试将交易视图图表小部件嵌入到反应组件中,但我不明白为什么它会被渲染两次

问题描述 投票:0回答:1

TradingViewWidget.jsx 是我尝试在其中嵌入交易视图小部件的组件。 问题是我无法弄清楚为什么我会得到同一个小部件的 2 个重复项。

我发现 TradingViewWidget.js 组件没有面临重新渲染问题,但仍然复制小部件。

// TradingViewWidget.jsx
import React, { useEffect, useRef, memo } from "react";

function TradingViewWidget() {
  const container = useRef();

  useEffect(() => {
    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);
  }, []);

  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-container__widget"></div>
      <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);

以下是我的浏览器的屏幕截图:

// App.js

import React from 'react'
import AppLayout from './components/AppLayout'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import TradingViewWidget from './components/Body/LeftBody/CoinGraph/TradingViewWidget'
import Error from './components/Error/Error'
import Body from './components/Body/Body'

const App = () => {

  const router = createBrowserRouter([
    {
      path: "/",
      element: <AppLayout />,
      children: [
        {
          path: "/",
          element: <Body />,
        },
        {
          path: "/coin",
          element: <TradingViewWidget />,
        }
      ],
      errorElement: <Error />
    }
  ])

  return (
    <RouterProvider router={router} />
  )
}

export default App

请帮忙...

我想阻止交易视图小部件被重复。

reactjs react-router chart.js embedded-resource
1个回答
0
投票
  1. 由于 React 18 严格模式的新行为,正在发生小部件的重复 - https://react.dev/blog/2022/03/29/react-v18#new-strict-mode-behaviors

为了避免这种情况,需要执行清理效果:

useEffect(() => {
  const currentContainer = container.current;
  
  const script = document.createElement("script");
  // init the script element 

  currentContainer.appendChild(script);

  return () => {
    currentContainer.removeChild(script);
  };
}, []);
  1. 您修改 DOM 的方式似乎不是 React 安全的。

https://react.dev/learn/manipulate-the-dom-with-refs

避免更改 React 管理的 DOM 节点。 修改、添加子元素或从 React 管理的元素中删除子元素可能会导致视觉结果不一致或像上面那样崩溃。

但是,这并不意味着你根本做不到。这需要谨慎。 您可以安全地修改 React 没有理由更新的 DOM 部分。例如,如果 JSX 中的某些部分始终为空,React 将没有理由触摸其子列表。因此,手动添加或删除元素是安全的。

将小部件附加到空的

<div>
会更安全。

© www.soinside.com 2019 - 2024. All rights reserved.