许多人在react中重新渲染TradingView图表

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

美好的一天。我已将图表添加到 SPA React 应用程序中。图表使用用户效果呈现在页面上。订单线也放置在图表上。页面上还有一个输入,根据此输入,orderLine 应该发生变化。然而,当绘制 orderLine 时,整个图表将被渲染为目标。另外,当我更改线的位置时,我将数据传输到相同的输入,并且所有内容都以相同的方式重新渲染。

如何解决这个问题而不重绘图表,而只重绘 orderLine?

export const TVChartContainer = ({
                   symbol= 'Binance:BTC/USDT',
                   interval= '1D',
                   containerId = 'tv_chart_container',
                   libraryPath = '/charting_library/',
                   chartsStorageUrl = 'https://saveload.tradingview.com',
                   chartsStorageApiVersion = '1.1',
                   clientId = 'tradingview.com',
                   userId = 'public_user_id',
                   fullscreen = false,
                   autosize = true,
                   studiesOverrides = {},
                   buyLine,
                   setBuyLine,
                 }) => {
  useEffect(() => {
    const widgetOptions = {
      debug: false,
      symbol: symbol,
      datafeed: Datafeed,
      interval: interval,
      container_id: containerId,
      library_path: libraryPath,
      locale: getLanguageFromURL() || 'en',
      disabled_features: ['use_localstorage_for_settings'],
      enabled_features: ['study_templates'],
      charts_storage_url: chartsStorageUrl,
      charts_storage_api_version: chartsStorageApiVersion,
      client_id: clientId,
      user_id: userId,
      fullscreen: fullscreen,
      autosize: autosize,
      studies_overrides: studiesOverrides,
    };
    const tvWidget = new widget(widgetOptions);

    tvWidget.onChartReady(() => {
      const order = tvWidget.chart().createOrderLine()
        .setText("Buy Line")
        .onMove(function () {
          setBuyLine(order.getPrice().toFixed(2));
        })
        .setLineLength(30)
        .setLineStyle(2)
        .setPrice(buyLine)
        .setLineColor('blue')
        .setQuantity(buyLine);
    })
  }, [symbol, buyLine]);
  return (
    <div
      id={containerId}
      className={'TVChartContainer'}
    />
  );
};
javascript reactjs tradingview-api
2个回答
0
投票

您在 useEffect 中设置

buyLine
并将其作为依赖项,这将陷入无限循环。删除该依赖项。


0
投票

您可以尝试使用 useLayoutEffect 来避免此问题,因为您在 useEffect 中添加了依赖项,然后您将在多次重新渲染中收到此问题。 ** 我更喜欢你,你应该为此使用类基函数 ** 由于这个问题将得到解决,并且您在下面有正确的更新数据,我将剪切类基函数的代码。

    class TradingChartComponent extends Component {
  constructor() {
    super(...arguments);

    this.currentKlineSubscription = {};

    this.state = {
      theme: this.props.theme,
    };

    this.params = {
      symbol: "Binance:BTC/USDT",
      interval: "1D",
      containerId: "TVChartContainer",
      libraryPath: "/charting_library/",
      chartsStorageUrl: "https://saveload.tradingview.com",
      chartsStorageApiVersion: "1.1",
      clientId: "tradingview.com",
      userId: "public_user_id",
      fullscreen: false,
      autosize: true,
      studiesOverrides: {},
      buyLine,
      setBuyLine,
    };

    this.tvWidget = null;

    this.datafeed = dataFeedObject(
      this,
      this.props.markets,
      this.props.decimalValue,
      this.props.currentMarket
    );

    this.setChart = (markets, currentMarket, decimalValue, pair1, pair2) => {
      this.datafeed = dataFeedObject(
        this,
        markets,
        decimalValue,
        currentMarket
      );
      const widgetOptions = {
        debug: false,
        symbol:
          pair1 != "" &&
          pair1 != undefined &&
          pair2 != "" &&
          pair2 != undefined &&
          pair2 + pair1,
        datafeed: this.datafeed,
        interval: this.params.interval,
        container_id: this.params.containerId,
        library_path: this.params.libraryPath,
        locale: "en",
        disabled_features: [
          "volume_force_overlay",
          "use_localstorage_for_settings",
          "header_symbol_search",
          "header_compare",
          "header_saveload",
          "display_market_status",
        ],
        enabled_features: [
          "show_animated_logo",
          "hide_left_toolbar_by_default",
          "chart_zoom",
          "chart_scroll",
          "study_templates",
          "create_volume_indicator_by_default",
        ],
        charts_storage_url: this.params.chartsStorageUrl,
        charts_storage_api_version: this.params.chartsStorageApiVersion,
        client_id: this.params.clientId,
        user_id: this.params.userId,
        fullscreen: this.params.fullscreen,
        autosize: this.params.autosize,
        popup_with: "000",
        enable_publishing: false,
        withdateranges: false,
        hide_side_toolbar: true,
        theme: this.props.theme,
        allow_symbol_change: false,
        details: true,
        hotlist: true,
        calendar: true,
        show_popup_button: true,
        popup_height: "100",
        overrides: {
          "mainSeriesProperties.showCountdown": true,
          "paneProperties.background":
            this.state.theme === "dark" ? "#000133" : "#000133",
          "symbolWatermarkProperties.transparency": 90,
          "scalesProperties.textColor": "#AAA",
          "scalesProperties.bgColor": "#AAA",
          "scalesProperties.fontSize": 11,
          "paneProperties.topMargin": 15,
          "mainSeriesProperties.candleStyle.upColor": GREEN_COLOR,
          "mainSeriesProperties.candleStyle.downColor": RED_COLOR,
          "mainSeriesProperties.candleStyle.wickUpColor": GREEN_COLOR,
          "mainSeriesProperties.candleStyle.wickDownColor": RED_COLOR,
          "mainSeriesProperties.candleStyle.borderColor": GREEN_COLOR,
          "mainSeriesProperties.candleStyle.borderUpColor": GREEN_COLOR,
          "mainSeriesProperties.candleStyle.borderDownColor": RED_COLOR,
          "mainSeriesProperties.barStyle.upColor": GREEN_COLOR,
          "mainSeriesProperties.barStyle.downColor": RED_COLOR,
          "mainSeriesProperties.barStyle.dontDrawOpen": true,
        },
      };
      this.tvWidget = new widget(widgetOptions);
      this.tvWidget.onChartReady(() => {
        const split_data = currentMarket.split("_");
        const cM = `${split_data[0]?.toLowerCase()}/${split_data[1]?.toLowerCase()}`;
        this.tvWidget.activeChart().setSymbol(cM, () => {
          print("Symbol set", cM);
        });
      });
    };

    this.updateChart = (currentMarket, decimalValue) => {
      this.tvWidget = null;
      this.datafeed = dataFeedObject(
        this,
        this.props.markets,
        decimalValue,
        currentMarket
      );
      const widgetOptions = {
        debug: false,
        symbol: symbol,
        datafeed: Datafeed,
        interval: interval,
        container_id: containerId,
        library_path: libraryPath,
        locale: getLanguageFromURL() || "en",
        disabled_features: ["use_localstorage_for_settings"],
        enabled_features: ["study_templates"],
        charts_storage_url: chartsStorageUrl,
        charts_storage_api_version: chartsStorageApiVersion,
        client_id: clientId,
        user_id: userId,
        fullscreen: fullscreen,
        autosize: autosize,
        studies_overrides: studiesOverrides,
      };
      this.tvWidget = new widget(widgetOptions);
      const split_data = currentMarket.split("_");
      const cM = `${split_data[0]?.toLowerCase()}/${split_data[1]?.toLowerCase()}`;
      if (this.tvWidget) {
        tvWidget.onChartReady(() => {
          const order = tvWidget
            .chart()
            .createOrderLine()
            .setText("Buy Line")
            .onMove(function () {
              setBuyLine(order.getPrice().toFixed(2));
            })
            .setLineLength(30)
            .setLineStyle(2)
            .setPrice(buyLine)
            .setLineColor("blue")
            .setQuantity(buyLine);
        });
      }
    };
  }

  componentWillReceiveProps(next) {
    if (
      next.currentMarket &&
      (!this.props.currentMarket ||
        next.currentMarket !== this.props.currentMarket)
    ) {
      if (this.props.currentMarket && this.tvWidget) {
        this.updateChart(next.currentMarket, next.decimalValue);
      } else {
        this.setChart(
          next.markets,
          next.currentMarket,
          next.decimalValue,
          next.pair1,
          next.pair2
        );
      }
    }

    if (Object.keys(next.kline).length > 0 && next.kline !== this.props.kline) {
      this.datafeed.onRealtimeCallback(next.kline);
    }

    if (next.theme && next.theme !== this.state.theme) {
      this.setState({ theme: next.theme }, () => {
        this.updateChart(next.currentMarket, next.decimalValue);
      });
    }

    if (next.decimalValue && this.props.decimalValue !== next.decimalValue) {
      this.updateChart(next.currentMarket, next.decimalValue);
    }
    if (next.refreshExchange !== this.props.refreshExchange) {
      this.updateChart(next.currentMarket, next.decimalValue);
    }
  }
  componentDidMount() {
    if (this.props.currentMarket) {
      this.setChart(
        this.props.markets,
        this.props.currentMarket,
        this.props.decimalValue,
        this.props.pair1,
        this.props.pair2
      );
    }
  }

  componentWillUnmount() {
    if (this.tvWidget) {
      try {
        this.tvWidget.remove();
      } catch (error) {
        console.log(`TradingChart unmount failed: ${error}`);
      }
    }
  }
  render() {
    return (
      <>
        <div id={this.params.containerId} />
      </>
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.