Welcome! Please see the About page for a little more info on how this works.

0 votes
in ClojureScript by

I am attempting to make use of the react-bootstrap module by leveraging NPM support in shadow-cljs.

First I add react-bootstrap and bootstrap to package.json:
$ yarn add react-bootstrap bootstrap

And then require react-bootstrap in my project:
(ns myproject.core (:require ["react-bootstrap" :as bs]))

The result is a runtime exception in the console:
TypeError: (0 , _uncontrollable.default) is not a function
... which curiously goes away after the first hot-reload.

The exception likely indicates a conflict in a nested NPM dependency. How can I identity and resolve the problem?

1 Answer

+4 votes

There are several ways to track down problems such as this.

Maybe a bit of background first. The JS community is currently in a transitional phase where they are figuring out how to do interop with CommonJS and ES6 (ES Modules) properly. babel and webpack both first supported sort of a "compatibility" mode but it wasn't very clean and will be deprecated with the release of webpack5. So basically anything looking at .default looks immediately suspicious and is indeed the cause of this problem.

First we need to identify what _uncontrollable even was. You can do that by looking at the source. You can check "Pause on caught exceptions" in the Chrome devtools which will start the debugger at relevant location and source for us. You'll find

var _uncontrollable = _interopRequireDefault(require("uncontrollable"));

So it was including the uncontrollable npm package. Quickly checking the node_modules/react-bootstrap/package.json file we see that it declares "uncontrollable": "^7.0.0" as a dependency.

A quick check with npm list reveals that another dependency however still wants an older version of uncontrollable. (output trimmed for the relevant parts).

├─┬ react-bootstrap@1.0.0-beta.12
│ ├─┬ react-overlays@1.2.0
│ │ ├─┬ uncontrollable@6.2.3
│ ├─┬ uncontrollable@7.0.1

Given that it is a different major version I presume they just aren't compatible.

This might work with webpack since it will just include both versions of uncontrollable in the build. shadow-cljs however does not support nested installs since we don't want duplicate packages.