frontend 성능 개선
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import type { StrategyDto } from '../../utils/backendApi';
|
||||
import {
|
||||
resolveVirtualTargetNames,
|
||||
@@ -11,6 +11,7 @@ import type { ChartRealtimeSource } from '../../hooks/useChartRealtimeData';
|
||||
import { buildConditionMetrics } from '../../utils/virtualSignalMetrics';
|
||||
import { resolveStrategyPrimaryTimeframe } from '../../utils/strategyToChartIndicators';
|
||||
import type { Timeframe } from '../../types';
|
||||
import { useIntersectionVisible } from '../../hooks/useIntersectionVisible';
|
||||
import VirtualLiveBadge from './VirtualLiveBadge';
|
||||
import type { VirtualLiveStatus } from '../../hooks/useVirtualTargetLiveStatus';
|
||||
import type { VirtualCardViewMode } from '../../utils/virtualTradingStorage';
|
||||
@@ -128,9 +129,12 @@ const VirtualTargetCard: React.FC<Props> = ({
|
||||
}, [running, lastTickAt, snapshot?.updatedAt]);
|
||||
const receiving = useLiveReceiveFlash(receiveSignal, running);
|
||||
const highlightReceiving = chartLiveReceiveHighlight && receiving;
|
||||
const { ref: cardRef, visible: cardInView } = useIntersectionVisible();
|
||||
const chartStreamEnabled = isChart && cardInView;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={cardRef}
|
||||
className={[
|
||||
'vtd-card',
|
||||
'vtd-card--signal',
|
||||
@@ -234,6 +238,7 @@ const VirtualTargetCard: React.FC<Props> = ({
|
||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||
chartPaneSeparator={chartPaneSeparator}
|
||||
chartTimeframe={chartTimeframe}
|
||||
chartStreamEnabled={chartStreamEnabled}
|
||||
/>
|
||||
) : (
|
||||
<VirtualTargetSignalPanel
|
||||
@@ -257,4 +262,4 @@ const VirtualTargetCard: React.FC<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default VirtualTargetCard;
|
||||
export default memo(VirtualTargetCard);
|
||||
|
||||
@@ -37,6 +37,8 @@ interface Props {
|
||||
fillHeight?: boolean;
|
||||
/** 미지정 시 전략 DSL 대표 분봉 사용 */
|
||||
chartTimeframe?: Timeframe;
|
||||
/** false — 뷰포트 밖 등: STOMP·히스토리 구독 중지 (기본 true) */
|
||||
chartStreamEnabled?: boolean;
|
||||
}
|
||||
|
||||
const noop = () => {};
|
||||
@@ -52,6 +54,7 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
||||
chartPaneSeparator,
|
||||
fillHeight = false,
|
||||
chartTimeframe,
|
||||
chartStreamEnabled = true,
|
||||
}) => {
|
||||
const { getParams, getVisualConfig } = useIndicatorSettings();
|
||||
const tfOptions = useMemo(() => resolveStrategyTimeframes(strategy), [strategy]);
|
||||
@@ -120,6 +123,7 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
||||
}, [applyRealtimeBar]);
|
||||
|
||||
const useUpbit = isUpbitMarket(market);
|
||||
const streamActive = useUpbit && chartStreamEnabled;
|
||||
|
||||
const { bars, barsMarket, isLoading } = useChartRealtimeData(
|
||||
market,
|
||||
@@ -127,15 +131,15 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
||||
useMemo(() => ({
|
||||
onTickUpdate: handleTickUpdate,
|
||||
onNewCandle: handleNewCandle,
|
||||
enabled: useUpbit,
|
||||
enabled: streamActive,
|
||||
source: chartRealtimeSource,
|
||||
}), [handleTickUpdate, handleNewCandle, useUpbit, chartRealtimeSource]),
|
||||
}), [handleTickUpdate, handleNewCandle, streamActive, chartRealtimeSource]),
|
||||
);
|
||||
|
||||
const { isLoadingMore } = useHistoryLoader({
|
||||
symbol: market,
|
||||
timeframe,
|
||||
isUpbit: useUpbit,
|
||||
isUpbit: streamActive,
|
||||
managerRef,
|
||||
});
|
||||
|
||||
@@ -199,12 +203,12 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
||||
}, [barsReady, applyPaneHeights, requestChartReload]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!useUpbit) return;
|
||||
if (!streamActive) return;
|
||||
void pinCandleWatch(market, timeframeToCandleType(timeframe));
|
||||
if (timeframeToCandleType(timeframe) !== '1m') {
|
||||
void pinCandleWatch(market, '1m');
|
||||
}
|
||||
}, [market, timeframe, useUpbit, running]);
|
||||
}, [market, timeframe, streamActive, running]);
|
||||
|
||||
return (
|
||||
<div className={`vtd-card-chart-panel${fillHeight ? ' vtd-card-chart-panel--fill' : ''}`}>
|
||||
@@ -239,7 +243,7 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
||||
)}
|
||||
<TradingChart
|
||||
key={`${market}-${timeframe}-${chartReloadTick}`}
|
||||
chartVisible
|
||||
chartVisible={chartStreamEnabled}
|
||||
bars={bars}
|
||||
barsMarket={barsMarket}
|
||||
market={market}
|
||||
|
||||
@@ -74,8 +74,8 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
||||
}, [viewMode, globalDisplayMode]);
|
||||
|
||||
const gridRemeasureKey = useMemo(
|
||||
() => `${viewMode}:${globalDisplayMode}:${targets.map(t => t.market).join(',')}:${Object.values(snapshots).map(s => s?.updatedAt ?? 0).join('|')}`,
|
||||
[viewMode, globalDisplayMode, targets, snapshots],
|
||||
() => `${viewMode}:${globalDisplayMode}:${targets.map(t => t.market).join(',')}`,
|
||||
[viewMode, globalDisplayMode, targets],
|
||||
);
|
||||
const [cardDisplayOverrides, setCardDisplayOverrides] = useState<Record<string, VirtualCardDisplayMode>>({});
|
||||
const [focusMarket, setFocusMarket] = useState<string | null>(null);
|
||||
|
||||
Reference in New Issue
Block a user