1

编辑:链接到Codesandbox上的复制:https ://codesandbox.io/s/exciting-worker-f5j1b

每次我尝试在 React 中将新数据注入我的图表(使用轻量级图表)时,我都会遇到一个错误,我需要帮助。

我怀疑这个问题与 React 渲染和重新渲染 DOM 的方式有关。在父组件中,我执行三个 API 调用,将历史图表数据从 Binance 传递给子组件(具有 4H、2H 和 1H 实际图表的组件)。在子组件中,我有一个 useEffect 挂钩,用于创建每个图表,然后使用轻量级图表方法注入数据chart.setData([Array])- 它还运行来自 Binance 的 Webhook,我使用该挂钩来使用轻量级图表方法更新图表chart.update({Object})

正如我所说 - 一切都有效,除了我想摆脱的数百个错误。

每当 Webhook 触发(并更新图表上的数据)以及子组件(但不是父组件)中有 API 调用时,就会发生错误——因此,当我注释掉API 调用时client.onmessage()getSignalData()我不会遇到错误,但我一直无法找到解决此问题的方法。

这是我的代码:

家长

 const GraphHero = () => {
      const [fourHourData, setFourHourData] = useState("");
      const [twoHourData, setTwoHourData] = useState("");
      const [oneHourData, setOneHourData] = useState("");
      const [key, setKey] = useState("fourHour");
      const [keyTwo, setKeyTwo] = useState("fourHour");
    
      useEffect(() => {
        //get historical data for charts and pass it down as prop
        const getFourHourData = () => {
          let url = `https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=4h&limit=1000`;
          fetch(url, {
            method: "GET",
            mode: "cors",
          })
            .then(checkStatus)
            .then(json)
            .then((response) => {
              const cData = response.map((d) => {
                return {
                  time: d[0] / 1000,
                  open: parseFloat(d[1]),
                  high: parseFloat(d[2]),
                  low: parseFloat(d[3]),
                  close: parseFloat(d[4]),
                };
              });
              setFourHourData(cData);
              console.log("Four hour API called");
            })
            .catch((error) => {
              console.log(error);
            });
        };
    
        const getTwoHourData = () => {
          let url = `https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=2h&limit=1000`;
          fetch(url, {
            method: "GET",
            mode: "cors",
          })
            .then(checkStatus)
            .then(json)
            .then((response) => {
              const cData = response.map((d) => {
                return {
                  time: d[0] / 1000,
                  open: parseFloat(d[1]),
                  high: parseFloat(d[2]),
                  low: parseFloat(d[3]),
                  close: parseFloat(d[4]),
                };
              });
              setTwoHourData(cData);
              console.log("Two hour API called");
            })
            .catch((error) => {
              console.log(error);
            });
        };
    
        const getOneHourData = () => {
          let url = `https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1h&limit=1000`;
          fetch(url, {
            method: "GET",
            mode: "cors",
          })
            .then(checkStatus)
            .then(json)
            .then((response) => {
              const cData = response.map((d) => {
                return {
                  time: d[0] / 1000,
                  open: parseFloat(d[1]),
                  high: parseFloat(d[2]),
                  low: parseFloat(d[3]),
                  close: parseFloat(d[4]),
                };
              });
              setOneHourData(cData);
              console.log("One Hour API called");
            })
            .catch((error) => {
              console.log(error);
            });
        };
    
        //initialize
        getFourHourData();
        getTwoHourData();
        getOneHourData();
      }, []);
    
      return (
      //I have HTML here that I deleted to shorten the code



<FirstChart chartData={fourHourData} setHistoricalData={setFourHourData}/>
<SecondChart chartData={twoHourData} setHistoricalData={setTwoHourData}/>
<ThirdChart chartData={oneHourData} setHistoricalData={setOneHourData}/>
      );
    };
    
    export default GraphHero;

子组件

    function FirstChart(fourHourData) {
  const [signals, setSignals] = useState("");
  const [loading, setLoading] = useState(true);
  const chartRef = React.useRef();

  useEffect(() => {
    console.log("DOM re-rendered.");
    const client = new W3CWebSocket(
      "wss://stream.binance.com:9443/ws/btcusdt@kline_4h"
    );
    const chart = createChart(chartRef.current, {
      watermark: {
        color: "white",
        visible: true,
        fontSize: 18,
        horzAlign: "left",
        vertAlign: "top",
      },
      timeScale: {
        timeVisible: true,
        borderColor: "whitesmoke",
      },
      layout: {
        backgroundColor: "#131722",
        textColor: "whitesmoke",
        fontSize: 12,
        fontFamily: "Arial",
      },
      priceScale: {
        borderColor: "whitesmoke",
      },
      grid: {
        vertLines: {
          style: 0,
          color: "rgba(70, 130, 180, 0.5)",
          visible: true,
        },
        horzLines: {
          style: 0,
          color: "rgba(70, 130, 180, 0.5)",
          visible: true,
        },
      },
    });
    const candleStickSeries = chart.addCandlestickSeries({
      upColor: "#0CCE6B",
      downColor: "#ED254E",
      borderVisible: false,
      wickVisible: true,
      borderColor: "white",
      wickColor: "white",
      borderUpColor: "#84f766",
      borderDownColor: "#ff6939",
      wickUpColor: "#84f766",
      wickDownColor: "#ff6939",
    });
    candleStickSeries.setData(fourHourData.chartData);
    client.onmessage = (event) => {
      let message = JSON.parse(event.data);
      candleStickSeries.update({
        time: message.k.t / 1000,
        open: message.k.o,
        high: message.k.h,
        low: message.k.l,
        close: message.k.c,
      });
    };

    const getSignalData = () => {
      fetch(url, {
        method: "GET",
        mode: "cors",
      })
        .then(checkStatus)
        .then(json)
        .then((response) => {
          const signalData = response.map((data) => {
            return {//Data operations I deleted because it's unrelated to chart//
            };
          });
          candleStickSeries.setMarkers(signalData);
          setSignals([...signalData.reverse()]);
          setLoading(false);
        })
        .catch((error) => {
          console.log(error);
        });
    };

    getSignalData();
    setInterval(function () {
      getSignalData();
      console.log("Fetched Long Active Chart again...");
    }, 60 * 1000);
    return () => {
      chart.remove();
    };
  }, [fourHourData]);

  return (
    <Row className="my-2">
      <Col
        lg={8}
        className="d-md-10 d-xl-block mx-auto mb-5 py-5 lightweight-chart"
        ref={chartRef}
      />
     </Row>
  );
}

export default FirstChart;

我花了几个小时试图解决这个问题,所以任何帮助都将不胜感激!

谢谢

4

0 回答 0