You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ApexCharts chart.render()报错排查:元素/Window未找到及可选链异常

解决Next.js中ApexCharts的三个核心问题

问题1:Element not found error

原因:你在组件函数顶层直接执行chart.render(),此时React还未完成DOM挂载,document.querySelector('#chart')找不到对应的元素。

修复:把图表初始化和渲染逻辑放到useEffect钩子中,确保DOM元素已挂载后再执行。同时要监听数据变化,当图表依赖的SaleCount和Dates更新时重新渲染,还要在组件卸载前销毁旧图表,避免内存泄漏。

问题2:可选链与刷新后报错反复

原因:初始状态下i是undefined,直接访问i.collections会触发错误;添加可选链后,数据未加载时si为undefined,si?.map不会执行,避免了报错。但刷新页面时数据需要重新请求,这段时间i仍为undefined,去掉可选链就会再次触发错误。

修复:

  • 给i设置初始默认值,比如useState({ collections: [] }),避免初始状态为undefined
  • 始终用可选链或空值合并运算符安全访问i.collections
  • 增加加载状态,数据未返回时显示加载提示,避免空数据导致图表异常

问题3:window not found error

原因:Next.js默认是服务端渲染(SSR),ApexCharts依赖浏览器的window对象,服务端渲染阶段不存在window,因此会报错。

修复:

  • 动态导入ApexCharts,仅在客户端环境加载
  • 用typeof window !== 'undefined'做判断,确保图表逻辑只在客户端执行
  • 或使用next/dynamic导入图表组件时禁用SSR

完整修正代码

import React, { useEffect, useState, useMemo } from "react";
import Head from 'next/head'
import styles from '../../../../styles/Home.module.css'
import CurrencyFormat from 'react-currency-format';
import Image from "next/image";

// 动态导入ApexCharts,规避SSR时的window问题
const loadApexCharts = async () => {
  if (typeof window !== 'undefined') {
    const { default: ApexCharts } = await import('apexcharts');
    return ApexCharts;
  }
  return null;
};

function App() {
  // 给i设置初始默认值,避免undefined
  const [i, setSeti] = useState({ collections: [] });
  const [countries, setCountries] = useState();
  const [loading, setLoading] = useState(true);
  let chartInstance = null; // 保存图表实例,用于销毁

  useEffect(() => {
    fetch(
      "https://api.reservoir.tools/collections/daily-volumes/v1?id=0xed5af388653567af2f388e6224dc7c4b3241c544&limit=10"
    )
      .then((response) => response.json())
      .then((response) => {
        setSeti(response);
        setLoading(false);
      })
      .catch(err => {
        console.error('数据请求失败:', err);
        setLoading(false);
      });
  }, []);

  // 用useMemo缓存数据处理结果,避免重复计算
  const { Dates, SaleCount } = useMemo(() => {
    const SaleCountt = [];
    const Datess = [];

    const si = i?.collections || [];
    si.forEach(item => {
      SaleCountt.push(Math.round(item.sales_count));
      const date = new Date(item.timestamp * 1000).toLocaleDateString("en-US");
      Datess.push(date);
    });

    return {
      Dates: Datess.reverse(),
      SaleCount: SaleCountt.reverse()
    };
  }, [i]);

  useEffect(() => {
    // 仅在客户端且数据加载完成后初始化图表
    if (!loading && typeof window !== 'undefined') {
      loadApexCharts().then(ApexCharts => {
        if (!ApexCharts) return;

        const options = {
          chart: {
            type: 'bar',
            height: 350
          },
          colors: ["#2E268D"],
          title: {
            text: 'Sale Count',
            align: 'left'
          },
          series: [
            {
              name: 'sales',
              data: SaleCount,
            }
          ],
          xaxis: {
            type: 'datetime',
            categories: Dates
          }
        };

        // 销毁旧图表,避免重复渲染
        if (chartInstance) {
          chartInstance.destroy();
        }

        const chartElement = document.querySelector('#chart');
        if (chartElement) {
          chartInstance = new ApexCharts(chartElement, options);
          chartInstance.render();
        }
      });
    }

    // 组件卸载时销毁图表
    return () => {
      if (chartInstance) {
        chartInstance.destroy();
      }
    };
  }, [loading, Dates, SaleCount]);

  if (loading) {
    return <div className={styles.Apps}>加载中...</div>;
  }

  return (
    <div className={styles.Apps}>
      <div className={styles.StatusTitles}>Apbo detailed analytics</div>
      <div className={styles.StatusBox}>
        <div className={styles.StatusBoxItemm}>
          <div id="chart" className={styles.chartt}></div>
        </div>
      </div>
    </div>
  );
}

export default App;

内容的提问来源于stack exchange,提问作者Sahankaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:10:38