美好的一天。我已将图表添加到 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'}
/>
);
};
您在 useEffect 中设置
buyLine
并将其作为依赖项,这将陷入无限循环。删除该依赖项。
您可以尝试使用 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} />
</>
);
}
}