编辑:链接到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;
我花了几个小时试图解决这个问题,所以任何帮助都将不胜感激!
谢谢