chartjs/chartjs-adapter-date-fns

Uncaught TypeError: Cannot read properties of undefined (reading '_adapters')

Shriniket33 opened this issue · 14 comments

chartjs-adapter-date-fns.bundle.js:6225 Uncaught TypeError: Cannot read properties of undefined (reading '_adapters')
at chartjs-adapter-date-fns.bundle.js:6225:10
at chartjs-adapter-date-fns.bundle.js:4:76
at chartjs-adapter-date-fns.bundle.js:5:2
(anonymous) @ chartjs-adapter-date-fns.bundle.js:6225
(anonymous) @ chartjs-adapter-date-fns.bundle.js:4
(anonymous) @ chartjs-adapter-date-fns.bundle.js:5

kurkle commented

did you import/require/load Chart.js before the adapter?

I ran into this error using Vite. Adding "chartjs-adapter-date-fns" to ssr.noExternal makes it go away. I previously had to mark "chart.js" as noExternal due to chartjs/Chart.js#9436 - perhaps there is a similar root cause?

thenbe commented

Adding "chartjs-adapter-date-fns" to ssr.noExternal makes it go away. I previously had to mark "chart.js" as noExternal due to chartjs/Chart.js#9436 - perhaps there is a similar root cause?

When using sveltekit, I've had to do the same; added both to ssr.noExternal. Otherwise, an error would be thrown when all of the following was true:

  1. Page is being rendered server-side.
  2. sveltekit is not running in dev mode

I'm getting this issue too when using VueJS.

I'm certain I've imported in the correct order, here is my component:

import { ref, toRef, watch } from 'vue';

import {
    Chart,
    TimeScale,
    ...
} from 'chart.js'

import 'chartjs-adapter-date-fns';
import { options } from './GraphConfig/TimelineGraph'

import {Bar, Line} from 'vue-chartjs'

Chart.register(
    ...
)

And here's the error:

[Vue warn]: Unhandled error during execution of async component loader
 |-> Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '_adapters')

My implementation isn't using Server-side rendering, so it can't be solved using the same process as some of the other replies.

I also attempted to include the adapter via a script tag in my HTML, loading after my Vue application to the same results. So this problem doesn't seem to be strictly related to the import process, but rather that this package imports correctly, but is unable to access the chart instance in order to override the _adapters

I may be incorrect here, but this seems to be that this package isn't "waiting" for an active ChartJS instance before actioning. My VueJS application runs as a deferred script, and I believe that this is causing issues here - this would also line up with users who are experiencing issues with SSR applications.

Is there a way to include the adapter in a different way? The way it currently does it, it just automatically overrides the _adapters, but if there's no ChartJS instance yet (because everything's being loaded as async), then it fails.

I've managed to solve it by way of a fork - and the way I solved it was to ensure it's not dynamically loading onto the chart instance.

https://github.com/danhanly/chartjs-adapter-date-fns/blob/master/src/index.js

I export the adapter code as an object constant, which I then import and apply to my chart instance manually (at a time when I know the chart instance is correctly loaded).

// ChartJS import
import {
    Chart,
    _adapters,
    ...
} from 'chart.js'

// my forked version
import { dateFnsAdapter } from "chartjs-adapter-date-fns"

// Within my component's setup() method
_adapters._date.override(dateAdapter)

This may help those users who had an issue with it on SSR too, as we are now in full control over when the override occurs with no in-package guesswork. Of course, there's the extra override line you have to manage, so swings and roundabouts.

lobaak commented

I'm also seeing this, is there no official fix yet?

Encountered the same issue

Same issue with webpack

Debugging, it seems that the prebundled dist files do not play nice with being re-bundled by the app becaue exports is no longer defined at the point of injecting dependencies, so it falls back to looking for the dependencies on the global.

To work around this I've added the following to my code

const ChartJs = require('chart.js');
const Chart = require('chart.js/auto');
const dateFns = require('date-fns');

// these are required because webpacking is a bit broken for the date-fns adapter
global.Chart = ChartJs;
global.dateFns = dateFns;

require('chartjs-adapter-date-fns');

Nothing here is working for me, so I tried the moment adapter and it works straight away :(

Nothing here is working for me, so I tried the moment adapter and it works straight away :(

This was actually my solution after hours of getting nowhere.

I saved the file and added from a local folder which fixed the issue.

I saved the file and added from a local folder which fixed the issue.

In the end, I did the same. This library is really simple, but it is not an ideal solution in general :(

I think I found the root cause. If you have 3 script files loading one after another, ie chart.js, than adapter.js, than app.js, the finished load order is often different. This can be checked by sorting by Waterfall > End Time in chrome developer.

To keep the order as written, Promise shall be used. I explained it here on Stackoverflow