From b028dbc537384583369ec93d5457dd20faa4e640 Mon Sep 17 00:00:00 2001 From: An Date: Tue, 17 Aug 2021 20:29:24 -0400 Subject: [PATCH] EventsCanvas: Clean up action to avoid memory leak (#37592) --- .../components/uPlot/geometries/EventsCanvas.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/grafana-ui/src/components/uPlot/geometries/EventsCanvas.tsx b/packages/grafana-ui/src/components/uPlot/geometries/EventsCanvas.tsx index fe2b5e7cbb1..38d7c9e85a4 100644 --- a/packages/grafana-ui/src/components/uPlot/geometries/EventsCanvas.tsx +++ b/packages/grafana-ui/src/components/uPlot/geometries/EventsCanvas.tsx @@ -1,5 +1,5 @@ import { DataFrame, DataFrameFieldIndex } from '@grafana/data'; -import React, { useLayoutEffect, useMemo, useState } from 'react'; +import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { usePlotContext } from '../context'; import { Marker } from './Marker'; import { XYCanvas } from './XYCanvas'; @@ -21,13 +21,25 @@ export function EventsCanvas({ id, events, renderEventMarker, mapEventToXYCoords // render token required to re-render annotation markers. Rendering lines happens in uPlot and the props do not change // so we need to force the re-render when the draw hook was performed by uPlot const [renderToken, setRenderToken] = useState(0); + const isMounted = useRef(false); useLayoutEffect(() => { + if (isMounted.current === false) { + return; + } config.addHook('draw', () => { setRenderToken((s) => s + 1); }); }, [config, setRenderToken]); + // clean up action to avoid memory leak + useEffect(() => { + isMounted.current = true; + return () => { + isMounted.current = false; + }; + }, []); + const eventMarkers = useMemo(() => { const markers: React.ReactNode[] = []; const plotInstance = plotCtx.plot;