Luizeradev
Luizeradev

Reputation: 193

Next.js: window is not defined

I'm trying to use apexcharts for a next.js application and it's returning me window is not defined.

I would love any help with that.

Does someone know what is happening and why?

import React from 'react';
import Chart from 'react-apexcharts';

export default class Graficos extends React.Component <{}, { options: any, series: any }> {
    constructor(props:any) {
        super(props);

        this.state = {
            options: {
            chart: {
                id: "basic-bar"
            },
            xaxis: {
                categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]
            }
            },
            series: [
            {
                name: "series-1",
                data: [30, 40, 45, 50, 49, 60, 70, 91]
            }
            ]
        };
    }
  
    render() {
        return (
            <div className="row">
                <h1>Gráfico Básico</h1>
                <div className="mixed-chart">
                    <Chart
                        options={this.state.options}
                        series={this.state.series}
                        type="bar"
                        width={500}
                    />
                </div>
            </div>
        );
    }
  }

Upvotes: 19

Views: 43752

Answers (7)

Raghav Sharma
Raghav Sharma

Reputation: 1100

For Next.js 14.2.3 The simplest solution is this:-

"use client"

import dynamic from "next/dynamic";

const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });

DONE

Upvotes: 1

Usmiech
Usmiech

Reputation: 301

I came here from google; my problem was a bit different but I want to post a solution somewhere for anyone struggling.

If you want to use Echarts with SvelteKit and you get "window is not defined "even though you imported {browser}, set ssr to false - downgrade node version to 16.

Upvotes: 0

I encountered similar problem while using echarts in Nextjs.
Echarts also contains lots of "window"s which make server side crash.
A simple way to solve this is to use "dynamic import" for any component that uses echarts and disable ssr.

const EChartsMap = dynamic(() => import('./EchartsMap'),   { ssr: false })

Upvotes: 1

cwtuan
cwtuan

Reputation: 1861

Why document or window is not defined in next.js?

function MyComponent() {
  // useMemo will run in server-side & client-side
  // Error: window is not defined in server
  const color = useMemo(()=> {
    return window.globalColor; 
  }, [])
  return <h1 className={`title ${color}`}>Hello World!</h1>
}

To fix this issue, you need to use useEffect to run the render only in the client-side. Here's an example code snippet:

function MyComponent() {
  const [color, setColor] = useState()
  useEffect(() => {
    setColor(window.globalColor)
  }, [])
  return <h1 className={`title ${color}`}>Hello World!</h1>
}

Furthermore, wrap the solution above in a hook

function useClientMemo<T>(fn: () => T, deps?: DependencyList): T {
  const [data, setData] = React.useState<T>();
  React.useEffect(() => {
    setData(fn());
  }, deps);
  return data;
}
export default useClientMemo;

Then, simply use:

function MyComponent() {
  const color = useClientMemo(()=> {
    return window.globalColor; 
  }, [])
  return <h1 className={`title ${color}`}>Hello World!</h1>
}

Explanation:

  • useEffect is executed only during client-side rendering.
  • useMemo is executed during both client-side rendering and server-side rendering.

Upvotes: -1

ben
ben

Reputation: 480

I encountered a type mismatch issue when working with dynamic imports with TypeScript did not work for me in Next.js 13. However, I resolved it by creating a new component called ApexChart.

In the new ApexChart component, I imported the react-apexcharts library and passed the required props to it. Here is an example of what the component looks like:

"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} />;
}

Upvotes: 13

Seyed Kazem Mousavi
Seyed Kazem Mousavi

Reputation: 457

if (typeof window !== "undefined") {
    host = window.location.host;
    console.log("host--------------", host);
  }

Upvotes: 7

Tim Ernsberger
Tim Ernsberger

Reputation: 811

One of Next.js's key features is that it can render parts of your React application on the server or even at build time. While this can be helpful in improving your page's performance, the downside is that the server does not provide the all same APIs that your application would have access to in the browser. In this case, there is no global window object defined.

Unfortunately, searching the source code for apexcharts.js turns up many references to window: https://github.com/apexcharts/apexcharts.js/search?q=window. This also occurs in their React wrapper: https://github.com/apexcharts/react-apexcharts/blob/ecf67949df058e15db2bf244e8aa30d78fc8ee47/src/react-apexcharts.jsx#L5. While there doesn't seem to be a way to get apexcharts to avoid references to window, you can prevent Next.js from using the chart on the server. The simplest way to do that is to wrap any reference to the code with a check for whether window is defined, e.g.

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

With apexcharts, you will also need to do this for the component import because the import alone will trigger a reference to window as shown in that second link. In order to get around that problem you will need to use a dynamic import as opposed to the normal import you currently have: https://nextjs.org/docs/advanced-features/dynamic-import

import dynamic from 'next/dynamic'

const Chart = dynamic(() => import('react-apexcharts'), { ssr: false });

Upvotes: 51

Related Questions