Fork me on GitHub
#reagent
<
2021-10-14
>
simonkatz11:10:46

I’m using react-bootstrap and Reagent. Versions: • reagent 1.1.0 • react 17.0.2 • react-dom 17.0.2 • Trying to upgrade from react-bootstrap 1.6.3 to 2.0.0-rc.0 With react-bootstrap 1.6.3 all is OK. With 2.0.0-rc.0 I get the following error:

React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
My code (which I put together last year with lots of help from Google, and which I don’t fully understand) is:
(ns my-ns (:require ["react-bootstrap/Col" :as rb-Col]))

(def ^:private component
  (memoize
   (fn [obj k & ks]
     (if (seq ks)
       (apply goog.object/getValueByKeys obj k ks)
       (goog.object/get obj k)))))

(defn ^:private reagent-ify [obj & ks]
  (fn [& args]
      (if ks
          (vec (concat [:> (apply component obj ks)] args))
        (vec (concat [:> obj] args)))))

(def b-Col rb-Col)

(def Col (reagent-ify b-Col))
Example use:
[Col {:class "col-3"} "Hello]
Any ideas what’s wrong?

p-himik11:10:44

You seem to be trying to replicate something that Reagent already provides. Not sure what resources you found on Google, but just reading Reagent examples and documentation would've been a much better bet. Remove everything except for the NS declaration, add something like [reagent.core :as r] to the :require. And just add (def Col (r/adapt-react-class rb-Coll)). That should do it.

simonkatz11:10:41

Thanks — that will simplify things! I’ve made those changes and I have the same problem — all good with react-bootstrap 1.6.3 but that same error with 2.0.0-rc.0. I’ll create a minimal example and see if I discover anything as a result.

p-himik12:10:02

How do you use Col?

p-himik12:10:49

It's probable that the API has simply changed between the versions and your current usage of it is simply incorrect and has nothing to do with CLJS at all.

simonkatz13:10:40

I now have a situation where I can’t even require “react-bootstrap/Col”. I’m getting NullPointerException: NAME $jscomp 66:8 [length: 96] [source_file: node_modules/react-bootstrap/cjs/Col.js] I don’t know what’s changed. I’ve looked in my node-modules at the Col directory and that looks just the same as the directories for other components. I’m going to take a break and continue later.

p-himik14:10:35

No clue but purging all caches, updating your build tools, and removing node_modules and installing the NPM packages again IMO is worth trying. If that doesn't work, create a minimal reproducible example - I'll take a look.

simonkatz16:10:14

@U2FRKM4TW Thanks! I’ve created a minimal repro at https://github.com/simon-katz/react-bootstrap-col-problem It’s a shadow-cljs project. The README has instructions on how to reproduce the issue.

simonkatz16:10:06

I’ve purged all the caches I know about, removed node-modules and reinstalled NPM packages, and I think I have all build tools up to date,

p-himik20:10:41

Add :js-options {:entry-keys ["module" "browser" "main"]} to the :compiler-options section. More details: https://shadow-cljs.github.io/docs/UsersGuide.html#js-entry-keys

simonkatz22:10:35

Minor correction: I had to add the :js-options at the same level as the :compiler-options.

👍 1
simonkatz22:10:41

Thanks, that does indeed fix the problem demonstrated in my minimal reproduction. Now, in my actual project, I’m back to the “type is invalid” errors. I’ll take another look tomorrow.

simonkatz22:10:17

BTW, the purpose of my reagent-ify is to allow things like: (def Accordion (reagent-ify b-Accordion)) (def Accordion_Body (reagent-ify b-Accordion "Body")) (def Accordion_Header (reagent-ify b-Accordion "Header")) (def Accordion_Item (reagent-ify b-Accordion "Item")) r/adapt-react-class only takes a single argument.

p-himik22:10:32

Why not (def Accordion_Body (r/adapt-react-class (.-Body b-Accordion)))? All you do is just getting the field in component, that's it - you can do it outside of adapt-react-class.

simonkatz11:10:21

Thanks. Yes, that’s much better.

👍 1
thheller07:10:50

please note that setting :entry-keys here is not actually the "fix". it just seems to avoid a bug in the closure compiler you otherwise run into. I can reproduce it but it happens deeply in closure compiler code and I don't see a way to fix it from shadow-cljs.

👍 2
thheller07:10:33

also seems to be polyfill related which makes it extra hard to track down

simonkatz12:10:27

@U05224H0W Thanks for your input. When you say “it happens deeply in closure compiler code”, are you referring to the error when requiring “react-bootstrap/Col” (which doesn’t happen if I have the require in my code when first compiling — only if I add the require in and have “shadow-cljs watch” load the changed code)?

simonkatz12:10:29

Or are you referring to the “React.createElement: type is invalid -- expected a string” errors I mentioned (which I get if the require is in place for the initial compile, and when I try to use Col?

simonkatz12:10:10

Just wondering if I have to give up on trying to upgrade from react-bootstrap 1.6.3 to 2.0.0-rc.0.

p-himik12:10:00

The React.createElement error is likely unrelated and is due to how you end up using Col exactly. If you add such a usage example to that same repo, I can take a look.

p-himik12:10:37

Or, assuming it's not too much code, you can just paste it here - it's likely that the problem is obvious.

simonkatz13:10:49

Thanks. My repo now has a new branch named “further-investigation”. In the “ui” namespace, there’s a var called demo-col-error? If false, the UI displays with no error. If true, I get the “type is invalid” error.

simonkatz13:10:26

Notes: I’ve changed the HTTP port to 8281 (so that I can run this and my real app at the same time. The value of rb-Col is different in kind to the values of rb-Row and rb-Container. See lines 12-14 of ui.cljs.

thheller13:10:32

I was referring to this error

Caused by:
NullPointerException: NAME $jscomp 66:8  [length: 96] [source_file: node_modules/react-bootstrap/cjs/Col.js]
	com.google.common.base.Preconditions.checkNotNull (Preconditions.java:897)
	com.google.javascript.jscomp.RemoveUnusedCode.getVarForNameNode (RemoveUnusedCode.java:891)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNameNode (RemoveUnusedCode.java:746)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNode (RemoveUnusedCode.java:571)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNormalOrOptChainGetProp (RemoveUnusedCode.java:629)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNode (RemoveUnusedCode.java:577)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseChildren (RemoveUnusedCode.java:1301)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseCall (RemoveUnusedCode.java:803)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNode (RemoveUnusedCode.java:498)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseDeclarationStatement (RemoveUnusedCode.java:1082)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNode (RemoveUnusedCode.java:550)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseChildren (RemoveUnusedCode.java:1301)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseFunction (RemoveUnusedCode.java:1442)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseNode (RemoveUnusedCode.java:467)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseChildren (RemoveUnusedCode.java:1301)
	com.google.javascript.jscomp.RemoveUnusedCode.traverseCall (RemoveUnusedCode.java:803)

thheller13:10:23

React.createElement: type is invalid -- expected a string could just be that the react-bootstrap package changed how they export the code

thheller13:10:37

so using :as may no longer be correct when they switch to using default exports

p-himik13:10:13

Even with the right imports (had to use :default instead of :as when the :js-options workaround was used), it still results in an error: Col.js:68 Uncaught TypeError: $jscomp.makeIterator is not a function And using :output-feature-set :es5 fixes it, so I guess @U06A9U5RP if you want to use the newer version of react-bootstrap, you're stuck with ES5 for now, unless there's some other workaround.

thheller13:10:21

please do not ever give this advice

thheller13:10:30

if setting :es5 happens to fix something that is a bug

thheller13:10:41

it should be reported and I will look into it

p-himik13:10:00

Isn't it the same with :js-options , given how it's just a workaround for a bug in GCC?

thheller13:10:52

$jscomp.makeIterator is not a function this means that a polyfill is missing. so the code was rewritten but somehow the polyfill was not accounted for properly

thheller13:10:12

that is likely a bug in shadow-cljs

p-himik13:10:27

Ah, so then not all $jscomp errors are equal, alright.

simonkatz13:10:39

@U2FRKM4TW @U05224H0W Thank you both for your help.

simonkatz13:10:19

@U05224H0W Will you be creating an issue for this? If so, please will you post a link so that I can follow it?

thheller13:10:23

$jscomp is just the object created for polyfills, so yeah it does many things and each error likely means something different

👍 1
thheller13:10:11

feel free to create an issue yourself

simonkatz13:10:29

Sure. Sorry —I misunderstood you.

thheller13:10:00

the first issue also might actually be coming from shadow-cljs. it compiles fine when the file is required in the initial compile. it only fails on incremental compile

👍 1
thheller13:10:31

so the cache might not be providing something properly it is supposed to provide or the GCC just doesn't like that I'm incrementally compiling something that was polyfilled. something it itself doesn't do.