Next.js:窗口未定义

Lui*_*dev 15 javascript typescript reactjs next.js apexcharts

我正在尝试将 apexcharts 用于 next.js 应用程序,但它返回窗口未定义。

\n

我希望得到任何帮助。

\n

有人知道发生了什么以及为什么吗?

\n
import React from 'react';\nimport Chart from 'react-apexcharts';\n\nexport default class Graficos extends React.Component <{}, { options: any, series: any }> {\n    constructor(props:any) {\n        super(props);\n\n        this.state = {\n            options: {\n            chart: {\n                id: "basic-bar"\n            },\n            xaxis: {\n                categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]\n            }\n            },\n            series: [\n            {\n                name: "series-1",\n                data: [30, 40, 45, 50, 49, 60, 70, 91]\n            }\n            ]\n        };\n    }\n  \n    render() {\n        return (\n            <div className="row">\n                <h1>Gr\xc3\xa1fico B\xc3\xa1sico</h1>\n                <div className="mixed-chart">\n                    <Chart\n                        options={this.state.options}\n                        series={this.state.series}\n                        type="bar"\n                        width={500}\n                    />\n                </div>\n            </div>\n        );\n    }\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

小智 40

Next.js 的关键功能之一是它可以在服务器上甚至在构建时渲染 React 应用程序的部分内容。虽然这有助于提高页面的性能,但缺点是服务器不提供应用程序在浏览器中可以访问的所有相同的 API。在这种情况下,没有window定义全局对象。

不幸的是,搜索 apexcharts.js 的源代码会发现许多对以下内容的引用windowhttps://github.com/apexcharts/apexcharts.js/search?q = window。这也发生在他们的 React 包装器中:https://github.com/apexcharts/react-apexcharts/blob/ecf67949df058e15db2bf244e8aa30d78fc8ee47/src/react-apexcharts.jsx#L5。虽然似乎没有办法获取 apexcharts 来避免引用window,但您可以阻止 Next.js 使用服务器上的图表。最简单的方法是包装对代码的任何引用,检查是否已window定义,例如

<div className="mixed-chart">
  {(typeof window !== 'undefined') &&
  <Chart
    options={this.state.options}
    series={this.state.series}
    type="bar"
    width={500}
  />
  }
</div>  
Run Code Online (Sandbox Code Playgroud)

对于 apexcharts,您还需要对组件导入执行此操作,因为单独导入将触发对window第二个链接中所示的引用。为了解决这个问题,您需要使用动态导入,而不是当前使用的普通导入: https: //nextjs.org/docs/advanced-features/dynamic-import

import dynamic from 'next/dynamic'

const Chart = dynamic(() => import('react-apexcharts'), { ssr: false });
Run Code Online (Sandbox Code Playgroud)


ben*_*ben 8

在Next.js 13中使用 TypeScript 进行动态导入时,我遇到了类型不匹配问题。不过,我通过创建一个名为 ApexChart 的新组件解决了这个问题。

在新的 ApexChart 组件中,我导入了react-apexcharts库并将所需的属性传递给它。以下是该组件的示例:

"use client";
import { useEffect, useState } from "react";

export default function ApexChart(props: any) {
  const [Chart, setChart] = useState<any>();
  const hasType = typeof props?.type !== "undefined";

  useEffect(() => {
    import("react-apexcharts").then((mod) => {
      setChart(() => mod.default);
    });
  }, []);

  return hasType && Chart && <Chart {...props} />;
}
Run Code Online (Sandbox Code Playgroud)