Cannot read properties of null (reading 'getContext') in React useEffect with dynamic chart initialization

14 hours ago 1
ARTICLE AD BOX

I am trying to initialize a Chart.js instance inside a React component using a useRef to target the canvas element. The component fetches data from an API asynchronously on mount.

If I initialize the chart with hardcoded static data, it works perfectly. However, when I try to initialize it after the async API fetch completes, it throws a fatal error and crashes the app.

import { useEffect, useRef, useState } from 'react'; import Chart from 'chart.js/auto'; export default function AnalyticsDashboard() { const canvasRef = useRef(null); const [analyticsData, setAnalyticsData] = useState(null); const [loading, setLoading] = useState(true); // 1. Fetch data on mount useEffect(() => { async function fetchMetrics() { try { const response = await fetch('/api/v1/analytics'); const data = await response.json(); setAnalyticsData(data); // e.g., { labels: ['A', 'B'], values: [10, 20] } } catch (err) { console.error("Failed to fetch", err); } finally { setLoading(false); } } fetchMetrics(); }, []); // 2. Initialize chart when data arrives useEffect(() => { if (!analyticsData) return; // ERROR THROWN HERE 👇 const ctx = canvasRef.current.getContext('2d'); const chartInstance = new Chart(ctx, { type: 'bar', data: { labels: analyticsData.labels, datasets: [{ data: analyticsData.values }] } }); return () => chartInstance.destroy(); }, [analyticsData]); if (loading) return <div>Loading metrics...</div>; return ( <div className="chart-container"> <h2>Monthly Traffic</h2> <canvas ref={canvasRef} id="trafficChart" width="400" height="200"></canvas> </div> ); }

The Error Console Output:

Uncaught TypeError: Cannot read properties of null (reading 'getContext') at AnalyticsDashboard.js:31:35 at commitHookEffectListMount (react-dom.development.js:23150:26) at commitPassiveMountOnFiber (react-dom.development.js:24408:13)

What I've tried:

I added if (!canvasRef.current) return; right before calling getContext. The error goes away, but the chart never renders at all—canvasRef.current just stays null forever.

If I remove the if (loading) return... early return state, it works, but then my page looks broken because it tries to render headings with blank data before the API finishes loading.

Why is the ref null inside the useEffect even though the canvas element is explicitly in the JSX? How do I fix the timing here?

Read Entire Article