2

I am using the react-apexcharts lib: https://github.com/apexcharts/react-apexcharts.

When I import a component that imports the lib into a page it works great when I navigate to it (client side routing). but when accessing the page directly with the URL I get an error:

Cannot read property 'document' of undefined
TypeError: Cannot read property 'document' of undefined
at Object.<anonymous> (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:433939)
at Object.<anonymous> (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:433950)
at s (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:395)
at Object.<anonymous> (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:169139)
at s (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:395)
at Object.<anonymous> (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:456290)
at s (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:395)
at C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:769
at C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:780
at C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:143
at Object.<anonymous> (C:\Users\a\Desktop\b\b-client\node_modules\apexcharts\dist\apexcharts.min.js:1:263)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)

It is worth noting that I am using next.js which using server side rendering.

The code is irrelevant IMO, I just created the example component from their github docs:

import Chart from 'react-apexcharts'
import React, { Component } from "react";

class ChartExample extends Component {
constructor(props) {
    super(props);

    this.state = {
        options: {
            chart: {
                id: 'apexchart-example'
            },
            xaxis: {
                categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998]
            }
        },
        series: [{
            name: 'series-1',
            data: [30, 40, 45, 50, 49, 60, 70, 91]
        },
        {
            name: 'series-2',
            data: [90, 210, 105, 50, 43, 99, 333, 4]
        }]
    }
}
render() {
    return (
        <Chart options={this.state.options} series={this.state.series} type="bar" width={500} height={320} />
    )
}
}

export default ChartExample;

And I import it regularly:

import ChartExample from "../../components/dashboard/ChartExample";

How can I fix this? I believe it is an issue with the server side rendering of next.js

Contentop
  • 1,163
  • 3
  • 20
  • 43
  • 4
    It looks like that library requires a document to run. Only render it on the server. https://stackoverflow.com/questions/49411796/how-do-i-detect-i-am-on-server-vs-client-in-next-js – Andy Ray Dec 22 '18 at 01:11

2 Answers2

8

One way to fix this issue is to use the dynamic import of nextjs

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

None the case your server will still complain about document on the first start, but this will not be reflected on the client-side

Ndifreke
  • 732
  • 1
  • 8
  • 13
5

The chart library needs a window object during rendering that is not present during SSR.

I would recommend to have a look at https://github.com/zeit/next.js/#dynamic-import (with option {ssr: false}) to skip rendering on the server. Also, the library is not loaded on the server what reduced your bundle size...

Rob
  • 5,353
  • 33
  • 34
  • Wouldn't this ruin the actual big benefits of next.js? I chose next.js mainly due to SSR because I wanted good SEO. Removing it beats this purpose – Contentop Dec 23 '18 at 17:30
  • 1
    Well, in some cases you don't have an alternative. Some 3rd party libs just don't support SSR and will crash on the server.. (same happens for leaflet). – Rob Dec 24 '18 at 13:09
  • ...But in most cases this is fine IMO, because it don't really makes sense from UX perspective to render a chart or map on the server... also search engine bots won't get any meaningful information out of it. – Rob Dec 24 '18 at 14:22
  • charts.js it is :) – Contentop Dec 24 '18 at 17:41
  • How can I do this on Angular? – Raman Joshi Apr 06 '20 at 08:29