MUI X Line Chart无法渲染含空值的部分数据系列
解决MUI X LineChart含空数据hover报错及线条起始问题
问题场景
使用MUI X LineChart时,某数据系列(如stateFullTime)前两个元素为null(对应2001、2006年无数据),期望该系列从(x:2011, y:53.2)处开始渲染,但hover图表时触发以下错误:
not-found-boundary.js:22 Uncaught TypeError: Cannot read properties of null (reading 'toLocaleString')
尝试用null、NaN均触发错误,用0虽能渲染但会在无数据年份显示标记,不符合需求。
解决方案
方案1:重构数据为{x,y}格式(推荐)
将含空值的系列数据重构为包含x(对应x轴标签)和y(数值)的对象数组,只保留有效数据点。这样LineChart会自动在对应x轴位置绘制线条,不会处理空值,从根源避免hover报错,同时线条自然从第一个有效数据点开始。
方案2:自定义Tooltip过滤空值
如果需要保留原数组结构,可通过自定义Tooltip组件,在渲染hover内容前判断数值是否有效,跳过空值的渲染,避免调用toLocaleString时出错。
修改后的代码
方案1实现(重构数据)
"use client"; import * as React from "react"; import { LineChart } from "@mui/x-charts/LineChart"; const suburbFullTime = [50, 53.1, 52.5, 53.5, 53.2]; // 重构state系列数据,只保留有效{x,y}数据点 const stateFullTime = [ { x: "2011", y: 53.2 }, { x: "2016", y: 57.2 }, { x: "2021", y: 57.1 }, ]; const australiaFullTime = [55.1, 55.3, 54.9, 57.2, 56.8]; export default function FullTimeEmploymentLineGraph() { return ( <div> <div className="flex flex-col justify-center"> <h1 className="mt-4 text-lg text-center font-bold">Full-time employment</h1> <div className="mx-auto -mt-10"> <LineChart xAxis={[ { data: ["2001", "2006", "2011", "2016", "2021"], }, ]} series={[ { id: "suburb", label: "Suburb", data: suburbFullTime, showMark: false, curve: "natural", }, { id: "state", label: "State", data: stateFullTime, // 使用重构后的{x,y}数据 showMark: false, curve: "natural", }, { id: "australia", label: "Australia", data: australiaFullTime, showMark: false, curve: "natural", }, ]} sx={{ "--ChartsLegend-itemWidth": "70px", "--ChartsLegend-itemMarkSize": "10px", "--ChartsLegend-labelSpacing": "5px", "--ChartsLegend-rootSpacing": "20px", }} legend={{ direction: "row", position: { vertical: "top", horizontal: "middle", }, }} width={600} height={400} margin={{ left: 70 }} /> </div> </div> </div> ); }
方案2实现(自定义Tooltip)
"use client"; import * as React from "react"; import { LineChart } from "@mui/x-charts/LineChart"; const suburbFullTime = [50, 53.1, 52.5, 53.5, 53.2]; const stateFullTime = [null, null, 53.2, 57.2, 57.1]; const australiaFullTime = [55.1, 55.3, 54.9, 57.2, 56.8]; export default function FullTimeEmploymentLineGraph() { return ( <div> <div className="flex flex-col justify-center"> <h1 className="mt-4 text-lg text-center font-bold">Full-time employment</h1> <div className="mx-auto -mt-10"> <LineChart xAxis={[ { data: ["2001", "2006", "2011", "2016", "2021"], }, ]} series={[ { id: "suburb", label: "Suburb", data: suburbFullTime, showMark: false, curve: "natural", }, { id: "state", label: "State", data: stateFullTime, showMark: false, curve: "natural", }, { id: "australia", label: "Australia", data: australiaFullTime, showMark: false, curve: "natural", }, ]} // 自定义Tooltip,过滤空值 tooltip={{ content: ({ items }) => ( <div style={{ padding: '8px', backgroundColor: 'white', borderRadius: '4px', boxShadow: '0 2px 8px rgba(0,0,0,0.15)' }}> {items.map((item) => { // 跳过null/NaN值的渲染 if (item.value === null || isNaN(item.value)) return null; return ( <div key={item.id} style={{ display: 'flex', gap: '8px', margin: '4px 0' }}> <span style={{ color: item.color, fontSize: '14px' }}>■</span> <span style={{ fontSize: '14px' }}>{item.label}: {item.value.toLocaleString()}</span> </div> ); })} </div> ), }} sx={{ "--ChartsLegend-itemWidth": "70px", "--ChartsLegend-itemMarkSize": "10px", "--ChartsLegend-labelSpacing": "5px", "--ChartsLegend-rootSpacing": "20px", }} legend={{ direction: "row", position: { vertical: "top", horizontal: "middle", }, }} width={600} height={400} margin={{ left: 70 }} /> </div> </div> </div> ); }
说明
- 方案1通过重构数据结构,彻底规避了空值的处理问题,同时让线条仅在有效数据区间绘制,视觉效果更符合需求。
- 方案2保留原数据结构,通过自定义Tooltip避免报错,但线条可能仍会连接空值点(取决于曲线类型),若需优化线条显示,可结合
skipNull属性(部分版本支持)或进一步处理数据。
内容的提问来源于stack exchange,提问作者Wilfred
相关产品推荐
相关产品推荐

