NextJS集成ChartJS报错:TypeError: Cannot read properties of null (reading 'useRef')
解决NextJS中使用ChartJS出现的
useRef错误 错误原因
- NextJS默认启用服务端渲染(SSR),但
react-chartjs-2内部依赖浏览器DOM环境,且使用了useRef这类客户端专属API,服务端渲染阶段无法获取DOM相关对象,因此抛出Cannot read properties of null (reading 'useRef')错误。 - 代码存在语法问题:
<canvas>是替换型元素,内部不能嵌套<h2>和<Line>组件,会导致渲染异常。
解决方案
方案1:动态导入组件并禁用SSR
在页面中通过NextJS的dynamic函数导入图表组件,强制组件仅在客户端渲染:
修改root/pages/admin/home.js:
import Head from 'next/head' import Image from 'next/image' import dynamic from 'next/dynamic' // 动态导入组件,禁用SSR const LineGraph = dynamic(() => import('../../components/admin/line'), { ssr: false, loading: () => <p>加载图表中...</p> }) export default function Home() { return ( <div className="container"> <Head> <title>Create Next App</title> <link rel="icon" href="/favicon.ico" /> </Head> <main> <LineGraph /> </main> </div> ) }
同时修复root/components/admin/line.js中的canvas嵌套问题:
import React from 'react'; import { Line } from 'react-chartjs-2'; import Chart from 'chart.js/auto'; const data = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [ { label: 'My First dataset', fill: false, lineTension: 0.1, backgroundColor: 'rgba(75,192,192,0.4)', borderColor: 'rgba(75,192,192,1)', borderCapStyle: 'butt', borderDash: [], borderDashOffset: 0.0, borderJoinStyle: 'miter', pointBorderColor: 'rgba(75,192,192,1)', pointBackgroundColor: '#fff', pointBorderWidth: 1, pointHoverRadius: 5, pointHoverBackgroundColor: 'rgba(75,192,192,1)', pointHoverBorderColor: 'rgba(220,220,220,1)', pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: [65, 59, 80, 81, 56, 55, 40] } ] }; const LineGraph = () => { return ( <div> <h2>Line Example</h2> <Line id="lineChart" data={data} width={400} height={400} /> </div> ); } export default LineGraph;
方案2:直接使用Chart.js核心库绕开SSR限制
若不想依赖react-chartjs-2,可直接使用chart.js核心库,通过useEffect确保仅在客户端初始化图表:
修改root/components/admin/line.js:
import React, { useEffect, useRef, useState } from 'react'; import Chart from 'chart.js/auto'; const data = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [ { label: 'My First dataset', fill: false, lineTension: 0.1, backgroundColor: 'rgba(75,192,192,0.4)', borderColor: 'rgba(75,192,192,1)', borderCapStyle: 'butt', borderDash: [], borderDashOffset: 0.0, borderJoinStyle: 'miter', pointBorderColor: 'rgba(75,192,192,1)', pointBackgroundColor: '#fff', pointBorderWidth: 1, pointHoverRadius: 5, pointHoverBackgroundColor: 'rgba(75,192,192,1)', pointHoverBorderColor: 'rgba(220,220,220,1)', pointHoverBorderWidth: 2, pointRadius: 1, pointHitRadius: 10, data: [65, 59, 80, 81, 56, 55, 40] } ] }; const LineGraph = () => { const chartRef = useRef(null); const [chartInstance, setChartInstance] = useState(null); useEffect(() => { // 仅在客户端初始化图表 if (chartRef.current && !chartInstance) { const ctx = chartRef.current.getContext('2d'); const newChart = new Chart(ctx, { type: 'line', data: data }); setChartInstance(newChart); } // 组件卸载时销毁图表,避免内存泄漏 return () => { if (chartInstance) { chartInstance.destroy(); } }; }, [chartInstance]); return ( <div> <h2>Line Example</h2> <canvas ref={chartRef} width={400} height={400} /> </div> ); } export default LineGraph;
额外注意事项
- 确保已安装所需依赖:
npm install chart.js react-chartjs-2(方案1需保留react-chartjs-2,方案2仅需chart.js) - 若使用NextJS 13+ App Router,需在图表组件顶部添加
'use client'指令,标记为客户端组件。
内容的提问来源于stack exchange,提问作者Seven
相关产品推荐
相关产品推荐

