React使用ApexCharts传递数组时触发TypeError错误求助
React + ApexCharts 数据传递 TypeError 问题解决
出现的错误
错误1:Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'x')
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'x') at t.value (apexcharts.common.js:6:113947) at t.value (apexcharts.common.js:6:113596) at t.value (apexcharts.common.js:6:120591) at t.value (apexcharts.common.js:6:123454) at t.value (apexcharts.common.js:15:37106) at t.eval [as create] (apexcharts.common.js:6:4473) at eval (apexcharts.common.js:15:36106) at new Promise (<anonymous>) at t.value (apexcharts.common.js:15:21675) at r.value (react-apexcharts.min.js:1:2927) at safelyCallComponentDidMount (react-dom.development.js:22877:14) at reappearLayoutEffectsOnFiber (react-dom.development.js:23531:11) at reappearLayoutEffects_complete (react-dom.development.js:24833:7) at reappearLayoutEffects_begin (react-dom.development.js:24821:7) at commitLayoutEffects_begin (react-dom.development.js:24644:11) at commitLayoutEffects (react-dom.development.js:24607:3) at commitRootImpl (react-dom.development.js:26818:5) at commitRoot (react-dom.development.js:26677:5) at finishConcurrentRender (react-dom.development.js:25976:9) at performConcurrentWorkOnRoot (react-dom.development.js:25804:7) at workLoop (scheduler.development.js:266:34) at flushWork (scheduler.development.js:239:14) at MessagePort.performWorkUntilDeadline (scheduler.development.js:533:21)
错误2:Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'toString')
Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'toString') at t.value (apexcharts.common.js:6:390713) at t.value (apexcharts.common.js:6:387088) at t.value (apexcharts.common.js:15:36720) at t.eval [as create] (apexcharts.common.js:6:4473) at eval (apexcharts.common.js:15:36106) at new Promise (<anonymous>) at t.value (apexcharts.common.js:15:21675) at r.value (react-apexcharts.min.js:1:2927) at invokeLayoutEffectMountInDEV (react-dom.development.js:25128:22) at invokeEffectsInDev (react-dom.development.js:27346:11) at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27322:5) at flushPassiveEffectsImpl (react-dom.development.js:27051:5) at flushPassiveEffects (react-dom.development.js:26979:14) at eval (react-dom.development.js:26764:9) at workLoop (scheduler.development.js:266:34) at flushWork (scheduler.development.js:239:14) at MessagePort.performWorkUntilDeadline (scheduler.development.js:533:21)
相关代码
页面组件(Axios请求+组件调用)
import Head from 'next/head'; import { Box, Container, Unstable_Grid2 as Grid } from '@mui/material'; import { Layout as DashboardLayout } from 'src/layouts/dashboard/admin/layout'; import axios from 'axios'; import { useEffect, useState } from 'react'; import { TotalSalesChart } from '../../sections/overview/Admin/TotalSalesChart'; const Page = () => { const [currentMonth, setCurrentMonth] = useState([]); const [data, setData] = useState([]); const [totalSalesArray, setTotalSalesArray] = useState([]); useEffect(() => { axios.get('http://localhost:8001/admin/getSalesPerMonth', { withCredentials: true }) .then((response) => { setCurrentMonth(response.data['currentMonth']); setData(response.data['pastMonths']); }).catch((error) => { console.log(error); }); },[]); const totalSales = currentMonth[0]?.totalSales; useEffect(() => { const salesArray = Object.values(data).map(month => month.totalSales); setTotalSalesArray([...salesArray.reverse(), totalSales]); }, [data]); return ( <> <Head> <title> Overview </title> </Head> <Box component="main" sx={{ flexGrow: 1, py: 8 }} > <Container maxWidth="xl"> <Grid container spacing={3} > <Grid xs={12} lg={8} > <TotalSalesChart chartSeries={[ { name: 'This year', data: totalSalesArray } ]} /> </Grid> </Grid> </Container> </Box> </> ); }; Page.getLayout = (page) => ( <DashboardLayout> {page} </DashboardLayout> ); export default Page;
图表组件代码
import DotsHorizontalIcon from '@untitled-ui/icons-react/build/esm/DotsHorizontal'; import { Box, Card, CardContent, CardHeader, IconButton, SvgIcon } from '@mui/material'; import { useTheme } from '@mui/material/styles'; import { Chart } from '../../../components/chart'; import { Scrollbar } from '../../../components/scrollbar'; const useChartOptions = () => { const theme = useTheme(); return { chart: { background: 'transparent', stacked: false, toolbar: { show: false }, zoom: { enabled: false } }, colors: [theme.palette.primary.main], dataLabels: { enabled: false }, fill: { gradient: { opacityFrom: 0.4, opacityTo: 0.1, stops: [0, 100] }, type: 'gradient' }, grid: { borderColor: theme.palette.divider, strokeDashArray: 2, xaxis: { lines: { show: false } }, yaxis: { lines: { show: true } } }, markers: { size: 6, strokeColors: theme.palette.background.default, strokeWidth: 3 }, stroke: { curve: 'smooth' }, theme: { mode: theme.palette.mode }, xaxis: { axisBorder: { show: false }, axisTicks: { show: false }, categories: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], labels: { offsetY: 5, style: { colors: theme.palette.text.secondary } } }, yaxis: { labels: { formatter: (value) => (value > 0 ? `${value}` : `${value}`), offsetX: -10, style: { colors: theme.palette.text.secondary } } } }; }; export const TotalSalesChart = (props) => { const { chartSeries } = props; const chartOptions = useChartOptions(); return ( <Box sx={{ backgroundColor: (theme) => theme.palette.mode === 'dark' ? 'neutral.800' : 'neutral.100', p: 3 }} > <Card> <CardHeader action={( <IconButton> <SvgIcon> <DotsHorizontalIcon/> </SvgIcon> </IconButton> )} title="Sales chart" /> <CardContent> <Scrollbar> <Box sx={{ height: 375, minWidth: 500, position: 'relative' }} > <Chart height={350} options={chartOptions} series={chartSeries} type="area" /> </Box> </Scrollbar> </CardContent> </Card> </Box> ); };
数据示例
totalSalesArray有效数据示例:
[6020, 6890, 600, 600, 60, 60, 60, 750, 750, 7550, 232, 1500]
问题原因与修复方案
原因分析
ApexCharts无法处理数据数组中的undefined值。代码中存在两个核心问题:
- 初始渲染时
totalSales为undefined(currentMonth初始是空数组,currentMonth[0]?.totalSales返回undefined),导致totalSalesArray混入无效值。 - 第二个
useEffect依赖项缺失totalSales,当currentMonth更新后,totalSales变化不会触发数组更新,造成数据不同步。
修复步骤
- 给
totalSales设置默认值,避免undefined:
const totalSales = currentMonth[0]?.totalSales ?? 0;
- 调整第二个
useEffect的依赖项,加入totalSales,同时给map中的month.totalSales设置默认值:
useEffect(() => { const salesArray = Object.values(data).map(month => month.totalSales ?? 0); setTotalSalesArray([...salesArray.reverse(), totalSales]); }, [data, totalSales]);
- (可选)添加加载状态,避免数据未准备好时渲染图表:
在页面组件中,仅当totalSalesArray长度匹配x轴分类数(12)时再渲染图表:
{totalSalesArray.length === 12 && ( <TotalSalesChart chartSeries={[ { name: 'This year', data: totalSalesArray } ]} /> )}
内容的提问来源于stack exchange,提问作者Ahmed Haitham
相关产品推荐
相关产品推荐

