Ben Logan Ben Logan - 5 days ago 6
React JSX Question

Importing an old ES5 module for use in a ReactJS component

I'm trying to use an ES5 module in a new ReactJS application and I'm struggling to understand how to correctly import that module, such that the main function within it can be found and executed.

I'm loading the module;

import 'air-datepicker';


I know I'm doing something wrong here and that it's not as simple as this, for an old library that doesn't have proper exports!

Anyway, then I should be able to manually initialise a date picker using an existing div like this;

$('#myDiv').datepicker();


I've tried multiple variations of the import and require, but I'm always getting the same error - 'datepicker is not a function'.

The library I'm experimenting with is air-datepicker. I've installed the module using npm without problems and I know the library works perfectly without React on a simple page loading the script manually in a script tag. My ReactJS app is a basic template created using 'create-react-app', from the FB tutorial pages.

Answer

Well, that's a day of my life that I'm never getting back!

The problem was caused by Babel import ordering. Import statements are hoisted - meaning they are evaluated first, before any other code (i.e. my window. assignments) are executed. This is 'by design' in babel.

The only way to avoid Babel hoisting, from what I can tell, is to avoid 'import' altogether and use require instead.

So, in the following order the global $ will have been set when you come to require air-datepicker. If you try to 'import' air-datepicker it won't work because Babel will evaluate all of your import statements before executing the window. assignment.

import $ from 'jquery';
window.$ = $;
require('air-datepicker');

There are one or two other approaches that also would have worked, but they are all less desirable because they need you to manually configure webpack - i.e. 'ejecting' the create-react-app config and going it alone...

Use the imports-loader;

// only works if you disable no-webpack-loader-syntax
require("imports?$=jquery!air-datepicker");

or, use the ProvidePlugin, making the module available for all modules.

Comments