From 131d2912d5a9478d6d243336feea7f5120cd6e01 Mon Sep 17 00:00:00 2001 From: Marko Djordjevic Date: Wed, 18 Feb 2026 15:19:44 +0100 Subject: [PATCH] fix: use chart.applyOptions() for theme changes instead of re-creating chart Remove resolvedTheme from the chart initialization useEffect dependency array so theme changes no longer destroy and re-create the entire chart. Add a separate useEffect that calls chartRef.current.applyOptions() with the new layout, grid, timeScale and rightPriceScale colors whenever resolvedTheme changes, avoiding the memory leak and flicker caused by full chart reconstruction on every theme toggle. Closes task 8.2. Co-Authored-By: Claude Sonnet 4.6 --- openspec/changes/code-review-fix/tasks.md | 2 +- src/components/CandleChart.tsx | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/openspec/changes/code-review-fix/tasks.md b/openspec/changes/code-review-fix/tasks.md index 73ba899..9af22cf 100644 --- a/openspec/changes/code-review-fix/tasks.md +++ b/openspec/changes/code-review-fix/tasks.md @@ -71,7 +71,7 @@ ## 8. Frontend — Memory Leaks & Performance - [x] 8.1 `[opus]` Fix SpanAnnotationManager preview primitive memory leak: replace `useState` with `useRef` for preview primitive, add cleanup on unmount (`src/components/SpanAnnotationManager.tsx:265-324`) -- [ ] 8.2 `[sonnet]` Use `chart.applyOptions()` for theme changes instead of re-creating chart (`src/components/CandleChart.tsx:333`) +- [x] 8.2 `[sonnet]` Use `chart.applyOptions()` for theme changes instead of re-creating chart (`src/components/CandleChart.tsx:333`) - [ ] 8.3 `[sonnet]` Remove `fitContent()` from reconciliation effect, only call on initial load (`src/components/SpanAnnotationManager.tsx:160`) - [ ] 8.4 `[opus]` Implement incremental primitive updates in SpanAnnotationManager: update only selection state on selection change, full reconciliation only on annotation list changes (`src/components/SpanAnnotationManager.tsx:104-161`) - [ ] 8.5 `[sonnet]` Add bounded prediction cache (max 100 entries, FIFO eviction) to `predictionCacheRef` (`src/app/page.tsx:195-199`) diff --git a/src/components/CandleChart.tsx b/src/components/CandleChart.tsx index b81a65a..7128fe6 100644 --- a/src/components/CandleChart.tsx +++ b/src/components/CandleChart.tsx @@ -345,7 +345,19 @@ const CandleChart = forwardRef( histogramSeriesRef.current = null; chart.remove(); }; - }, [isEmpty, mounted, resolvedTheme]); + }, [isEmpty, mounted]); + + // Apply theme changes without re-creating the chart + useEffect(() => { + if (!chartRef.current) return; + const colors = getChartColors(); + chartRef.current.applyOptions({ + layout: colors.layout, + grid: colors.grid, + timeScale: { borderColor: colors.timeScale.borderColor }, + rightPriceScale: { borderColor: colors.rightPriceScale.borderColor }, + }); + }, [resolvedTheme]); // Load candle data into chart useEffect(() => {