실시간 차트 갱신문제 수정
This commit is contained in:
@@ -5,10 +5,10 @@ import { ChartManager } from '../utils/ChartManager';
|
||||
import { setIndicatorChartContext } from '../utils/indicatorRegistry';
|
||||
import { DISPLAY_COUNT } from '../hooks/useUpbitData';
|
||||
|
||||
/** Upbit 실시간 — 초기 히스토리가 이 개수 미만이면 setData 하지 않음 (종목 전환 직후 1~2봉만 로드되는 깨짐 방지) */
|
||||
/** Upbit 실시간 — 초기 히스토리가 이 개수 미만이면 setData 하지 않음 (종목 전환 직후 sparse 봉 → 캔들 폭 비정상) */
|
||||
const MIN_BARS_FOR_FULL_RELOAD = Math.min(50, Math.floor(DISPLAY_COUNT / 4));
|
||||
|
||||
/** 종목 전환 직후 stale/partial 데이터 차단 — fetch 완료(barsMarket 확정) 후 sparse history도 렌더 허용 */
|
||||
/** 종목 전환 직후 stale/partial 데이터 차단 — fetch 완료(barsMarket 확정) + 충분한 히스토리만 렌더 */
|
||||
function canApplyChartBars(
|
||||
barData: OHLCVBar[],
|
||||
barsMarket: string | null | undefined,
|
||||
@@ -17,9 +17,8 @@ function canApplyChartBars(
|
||||
if (barData.length === 0) return false;
|
||||
if (barsMarket === undefined) return true;
|
||||
if (barsMarket == null || barsMarket !== market) return false;
|
||||
if (!market.startsWith('KRW-')) return true;
|
||||
if (barData.length >= MIN_BARS_FOR_FULL_RELOAD) return true;
|
||||
return barData.length >= 2;
|
||||
if (!market.startsWith('KRW-')) return barData.length >= 2;
|
||||
return barData.length >= MIN_BARS_FOR_FULL_RELOAD;
|
||||
}
|
||||
import DrawingCanvas, { hitTestDrawing } from './DrawingCanvas';
|
||||
import PaneLegend, { type PaneLegendProps } from './PaneLegend';
|
||||
@@ -74,6 +73,8 @@ interface TradingChartProps {
|
||||
* ChartSlot 에서 멀티차트 첫 마운트 시 sync range 를 재적용하는 데 사용.
|
||||
*/
|
||||
onDataLoaded?: () => void;
|
||||
/** setData 직후 캔들·볼륨 반영 완료 — 실시간 틱 허용 시점 (지표 로드 전) */
|
||||
onCandlesReady?: () => void;
|
||||
/** 보조지표 pane 순서 변경 (드래그 핸들): fromId 를 insertBeforeId 앞으로 이동 (null = 맨 뒤) */
|
||||
onReorderIndicators?: (fromId: string, insertBeforeId: string | null) => void;
|
||||
/** 보조지표 pane 병합 */
|
||||
@@ -109,6 +110,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
magnifierEnabled = false,
|
||||
onMagnifierClose,
|
||||
onDataLoaded,
|
||||
onCandlesReady,
|
||||
onReorderIndicators,
|
||||
onMergeIndicators,
|
||||
onSplitIndicatorPane,
|
||||
@@ -385,13 +387,13 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
do {
|
||||
reloadCoalesceRef.current = false;
|
||||
const gen = reloadGenRef.current;
|
||||
const barData = barsRef.current.length > 0 ? barsRef.current : newBars;
|
||||
if (barData.length === 0) break;
|
||||
if (newBars.length === 0) break;
|
||||
|
||||
reloadSafetyTimers.current.forEach(clearTimeout);
|
||||
reloadSafetyTimers.current = [];
|
||||
|
||||
barsRef.current = barData;
|
||||
barsRef.current = newBars;
|
||||
const barData = newBars;
|
||||
|
||||
mgr.setData(barData, ct, th);
|
||||
if (gen !== reloadGenRef.current) {
|
||||
@@ -402,6 +404,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
mgr.setLogScale(ls);
|
||||
mgr.setDisplayTimezone(displayTimezone, timeframe);
|
||||
commitCandleLayout(mgr);
|
||||
onCandlesReady?.();
|
||||
|
||||
let stale = false;
|
||||
for (const ind of inds) {
|
||||
@@ -489,7 +492,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
queueFullReload();
|
||||
}
|
||||
}
|
||||
}, [applyPaneLayout, commitCandleLayout, onDataLoaded, displayTimezone, timeframe, market, queueFullReload, queueIndicatorRecovery]);
|
||||
}, [applyPaneLayout, commitCandleLayout, onCandlesReady, onDataLoaded, displayTimezone, timeframe, market, queueFullReload, queueIndicatorRecovery]);
|
||||
|
||||
useEffect(() => {
|
||||
reloadAllRef.current = reloadAll;
|
||||
@@ -822,6 +825,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
reloadCoalesceRef.current = false;
|
||||
reloadSafetyTimers.current.forEach(clearTimeout);
|
||||
reloadSafetyTimers.current = [];
|
||||
managerRef.current?.clearForSymbolChange();
|
||||
managerRef.current?.cancelPendingIndicatorUpdates();
|
||||
}, [market, timeframe]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user