Problem running newest version of @mui/x-date-pickers - bundler bug?

I haven’t finished the investigation yet but I’m going on a “micro retirement” (newspeak for vacation) next week so I thought I’d post my findings so far.

Our app is an SPA with React + MUI (Material UI), Meteor 3.3.

After what I thought would be a simple update of @mui/x-date-pickers from 7.7 to 8.8, it stopped working and gave the error signalling that the Localization context was not properly set up.

MUI X: Can not find the date and time pickers localization context.
It looks like you forgot to wrap your component in LocalizationProvider.
This can also happen if you are bundling multiple versions of the @mui/x-date-pickers package

Even this simple code did not work:

    <LocalizationProvider
      dateAdapter={AdapterMoment}
      adapterLocale={moment.locale()}
      dateLibInstance={moment}
    >
      <DatePicker
          value={new Date()}
          onChange={() => {}}
    </LocalizationProvider>

I could not see any duplicate version imports so I wondered wth is going on?

Then I peeked into the meteor bundler output and found something interesting that I think is the problem but I haven’t come up with a way to verify it yet:

The modules.js file in .meteor/local/build/programs/web.browser/packages contains BOTH the commonjs and the esm distribution files for @mui/x-date-pickers, and there is a comment in the source file about how the singleton React context used for LocalizationProvider is marked with “TODO v9: Remove this public export”.

So my educated guess is that the esm and commonjs implementations FOR THE SAME COMPONENT overwrite this global in a bad way.

Questions:

Can I make the meteor bundler NOT import the esm distribution of the lib? Is it a bug that needs to be fixed? How?

This is what the module looks like inside node_modules. Notice one index.js file in the root one inside ./esm

image

More code dumps - these are from the produced modules.js file

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                     //
// node_modules/@mui/x-date-pickers/esm/LocalizationProvider/LocalizationProvider.js                                   //
//                                                                                                                     //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                       //
'use client';module.export({PickerAdapterContext:()=>PickerAdapterContext,MuiPickersAdapterContext:()=>MuiPickersAdapterContext,LocalizationProvider:()=>LocalizationProvider},true);let _extends;module.link("@babel/runtime/helpers/esm/extends",{default(v){_extends=v}},0);let _objectWithoutPropertiesLoose;module.link("@babel/runtime/helpers/esm/objectWithoutPropertiesLoose",{default(v){_objectWithoutPropertiesLoose=v}},1);let React;module.link('react',{"*"(v){React=v}},2);let PropTypes;module.link('prop-types',{default(v){PropTypes=v}},3);let useThemeProps;module.link('@mui/material/styles',{useThemeProps(v){useThemeProps=v}},4);let _jsx;module.link("react/jsx-runtime",{jsx(v){_jsx=v}},5);

and then further down the file:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                     //
// node_modules/@mui/x-date-pickers/LocalizationProvider/LocalizationProvider.js                                       //
//                                                                                                                     //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                       //
"use strict";
'use client';

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;

Ideally, you could use the Dayjs which has the smallest footprint in a codebase among the time libraries.

I believe you expect moment.locale() to read the browser locale and return a string. That is not correct and not enough.
You need to avail of all locale(s) by importing them in your definition.

import moment from 'moment';
import 'moment/locale/fr'; // Make sure the locale is loaded
import 'moment/locale/en'; // Make sure the locale is loaded
import 'moment/locale/ar'; // Make sure the locale is loaded

Let’s say you import 3 locales and if the browser is on something else return (set) a default.

moment.locale('ar')

Determine your locale outside the provider and pass it as a string.

<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="ar">
  <DatePicker
    label="Pick a date"
    value={moment()} // this should be a moment date object.
    onChange={() => {}}
  />
</LocalizationProvider>

I don’t think you need this: dateLibInstance

I don’t want to derail this thread so I will only say that the code you’re commenting on works fine. It’s the npm package update that breaks things

I was able to find a workaround using yarn’s patch mechanism to simply remove all the files in the /esm directory. Just removing index.js would probably have been enough.
So there is a problem here with packages that have both a commonjs and an esm distribution.

I always use the latest versions of certain libraries and never had a problem with this one. I had this problem with react-router but not with anything from MUI.
It would be interesting to understand why this is happening to you if this is the only problem.
Do you have this in your project’s package json "type": "commonjs",?!

I came back from vacation and the problem went away without needing to patch the package - maybe they fixed the global singleton TODO.

I will keep your solution in mind for the next 1000 problems in my life …

2 Likes