종목변경 시 캔들차트 사라지는 현상 수정

This commit is contained in:
Macbook
2026-05-24 21:51:27 +09:00
parent af230a4233
commit 3c66c562d8
14 changed files with 288 additions and 219 deletions
+19 -5
View File
@@ -53,6 +53,8 @@ interface Options {
interface Return {
bars: OHLCVBar[];
/** bars 가 어느 종목 기준인지 (로딩 중·전환 직후 null) */
barsMarket: string | null;
latestBar: OHLCVBar | null;
wsStatus: WsStatus;
isLoading: boolean;
@@ -105,6 +107,7 @@ export function useStompChartData(
): Return {
const candleType = timeframeToCandleType(timeframe);
const [bars, setBars] = useState<OHLCVBar[]>([]);
const [barsMarket, setBarsMarket] = useState<string | null>(null);
const [latestBar, setLatestBar] = useState<OHLCVBar | null>(null);
const [wsStatus, setWsStatus] = useState<WsStatus>('connecting');
const [isLoading, setIsLoading] = useState(true);
@@ -117,13 +120,17 @@ export function useStompChartData(
/** 1m 봉 volume 스냅샷 — 상위 분봉 volume 델타 계산용 */
const last1mVolRef = useRef<number>(0);
const last1mTimeRef = useRef<number>(0);
/** 초기 히스토리 로드 완료 전에는 차트 직접 갱신 콜백을 호출하지 않음 */
const historyReadyRef = useRef(false);
useEffect(() => {
if (opts.enabled === false) return;
let cancelled = false;
historyReadyRef.current = false;
setIsLoading(true);
setError(null);
setBars([]);
setBarsMarket(null);
barsRef.current = [];
last1mVolRef.current = 0;
last1mTimeRef.current = 0;
@@ -134,6 +141,8 @@ export function useStompChartData(
.then(newBars => {
if (cancelled) return;
barsRef.current = newBars;
historyReadyRef.current = newBars.length > 0;
setBarsMarket(market);
setBars(newBars);
setLatestBar(newBars[newBars.length - 1] ?? null);
lastTimeRef.current = newBars[newBars.length - 1]?.time ?? 0;
@@ -159,10 +168,11 @@ export function useStompChartData(
const pushBar = (bar: OHLCVBar) => {
const current = barsRef.current;
const notifyChart = historyReadyRef.current;
if (current.length === 0) {
barsRef.current = [bar];
setLatestBar(bar);
optsRef.current.onNewCandle(bar);
if (notifyChart) optsRef.current.onNewCandle(bar);
lastTimeRef.current = bar.time;
return;
}
@@ -170,16 +180,16 @@ export function useStompChartData(
if (bar.time === last.time) {
barsRef.current[current.length - 1] = bar;
setLatestBar(bar);
optsRef.current.onTickUpdate(bar);
if (notifyChart) optsRef.current.onTickUpdate(bar);
} else if (bar.time > last.time) {
barsRef.current = [...current, bar];
setLatestBar(bar);
optsRef.current.onNewCandle(bar);
if (notifyChart) optsRef.current.onNewCandle(bar);
} else {
const patched = { ...bar, time: last.time };
barsRef.current[current.length - 1] = patched;
setLatestBar(patched);
optsRef.current.onTickUpdate(patched);
if (notifyChart) optsRef.current.onTickUpdate(patched);
}
lastTimeRef.current = bar.time;
};
@@ -255,12 +265,15 @@ export function useStompChartData(
setWsStatus('connecting');
setError(null);
historyReadyRef.current = false;
last1mVolRef.current = 0;
last1mTimeRef.current = 0;
void pinChartWatch(market, STOMP_TICK_CANDLE_TYPE);
const topic = `/sub/charts/${market}/${STOMP_TICK_CANDLE_TYPE}`;
let alive = true;
const unsub = subscribeStompTopic(topic, msg => {
if (!alive) return;
setWsStatus('connected');
const data = parseStompJson<StompCandlePayload>(msg);
if (data?.time == null || typeof data.time !== 'number') return;
@@ -270,11 +283,12 @@ export function useStompChartData(
const t = window.setTimeout(() => setWsStatus('connected'), 800);
return () => {
alive = false;
window.clearTimeout(t);
unsub();
setWsStatus('disconnected');
};
}, [market, timeframe, opts.enabled, applyCandle]);
return { bars, latestBar, wsStatus, isLoading, error };
return { bars, barsMarket, latestBar, wsStatus, isLoading, error };
}