ARTICLE AD BOX
I recently upgraded our application to React 19 and started refactoring our legacy useEffect DOM cleanups to use the new Ref Cleanup Function feature (where callback refs can return a cleanup function).
The refactoring works perfectly across 95% of our app, but I am hitting a cryptic crash in a dashboard component that uses useDeferredValue and conditional rendering.
Here is a simplified version of the breaking component. It dynamically renders a third-party chart engine inside a container element based on a deferred search query:
import { useState, useDeferredValue } from 'react'; import { ExternalChartEngine } from 'awesome-charts'; export default function Dashboard({ searchTerms }) { const [showMetrics, setShowMetrics] = useState(true); // Deferring the search terms to keep the UI responsive const deferredSearch = useDeferredValue(searchTerms); if (!showMetrics) return <div>Metrics Hidden</div>; return ( <div className="dashboard-container"> <div ref={(element) => { if (!element) return; // Initialize the third-party chart const chartInstance = ExternalChartEngine.init(element, { query: deferredSearch }); // React 19 Cleanup function return () => { if (chartInstance) { chartInstance.destroy(); } }; }} /> </div> ); }Whenever searchTerms changes rapidly (triggering the deferred transition) and a user simultaneously toggles setShowMetrics(false), the application completely crashes with the following console error inside React's reconciler:
Uncaught TypeError: Cannot read properties of null (reading 'destroy') at safelyCallDestroy (react-dom.development.js:22943) at commitDeletionEffectsOnFiber (react-dom.development.js:24210) at recursivelyTraverseDeletionEffects (react-dom.development.js:24120)What I've Tried
If I change the ref back to a standard useRef and handle the initialization/cleanup inside a standard useEffect, the crash disappears.
If I remove useDeferredValue, the crash disappears.
Why is returning a cleanup function from an inline callback ref failing specifically during a deferred render transition?
