React.createElement: 在 ClojureScript 中使用 react-bootstrap 类型无效
React.createElement: type is invalid using react-bootstrap in ClojureScript
我正在尝试在重新构建项目中使用 react-bootstrap。我已经安装了 react-bootstrap with
npm install react-bootstrap
并像下面这样使用它的组件:
(:require
;; ...
["react-bootstrap/Button" :as Button]
;; ...
(defn main-panel []
[:div
[:> Button "Hit me"]
]])
一切正常,直到我尝试制作下拉菜单,更准确地说,直到我尝试使用 DropdownMenu
。我把它插入the example之后的打嗝的那一刻
[:> Dropdown
[:> DropdownToggle "button"]
[:> DropdownMenu {:variant :dark}
[:> DropdownItem "action1"]
[:> DropdownItem "action2"]
[:> DropdownItem "action3"]]]
我在浏览器控制台中得到以下信息:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
我对整个前端世界都非常陌生,所以我不确定是我做错了什么,还是 react-bootstrap、试剂或任何其他部分存在错误的项目。
这是这个问题的 MWE:https://github.com/lockie/react-bootstrap-cljs-demo
文档中有一节介绍如何 translate ES import
npm 包。
在那里你会发现 ["react-bootstrap/Button" :as Button]
应该是 ["react-bootstrap/Button$default" :as Button]
而不是(翻译 import Button from "react-bootstrap/Button";
)
但这仅在使用实际 ESM 代码时适用。然而,react-bootstrap
包是一个包含 ESM 和 CommonJS 的混合包。 shadow-cljs 在这种情况下默认情况下不会使用 ESM。
因此,一种选择是 shadow-cljs 使用 ESM 代码,方法是将其包含在构建配置中。
:js-options {:entry-keys ["module" "browser" "main"]}
这将需要为每个需求使用 $default
,因为它们都是默认导出。
另一种选择是使用默认的 CommonJS 代码。然而,这似乎打包不一致,这意味着大多数都能正常工作,但有一个例外。如果我将您的示例代码更改为
,它就可以正常工作
(ns react-bootstrap-cljs-demo.views
(:require
[re-frame.core :as re-frame]
[react-bootstrap-cljs-demo.subs :as subs]
["react-bootstrap/Button" :as Button]
["react-bootstrap/Dropdown" :as Dropdown]
["react-bootstrap/DropdownItem" :as DropdownItem]
["react-bootstrap/DropdownMenu$default" :as DropdownMenu]
["react-bootstrap/DropdownToggle" :as DropdownToggle]
))
因此,只有 DropdownMenu
以需要 $default
的方式包含在内。似乎 react-bootstrap
方面可能存在疏忽或错误。 shadow-cljs
只是跟随磁盘上的内容。
选择哪种方法由您决定。使用 ESM 可能会导致其他软件包出现问题,或者可能工作得很好。一切都取决于您实际发布的包。
如何解决这个问题?
作为一个小指南:我通过记录所需的 :as
别名并在浏览器控制台中查看它来解决这个问题。
就这样
(ns react-bootstrap-cljs-demo.views
(:require
[re-frame.core :as re-frame]
[react-bootstrap-cljs-demo.subs :as subs]
["react-bootstrap/Button" :as Button]
["react-bootstrap/Dropdown" :as Dropdown]
["react-bootstrap/DropdownItem" :as DropdownItem]
["react-bootstrap/DropdownMenu$default" :as DropdownMenu]
["react-bootstrap/DropdownToggle" :as DropdownToggle]
))
(js/console.log "Button" Button)
(js/console.log "Dropdown" Dropdown)
(js/console.log "DropdownItem" DropdownItem)
(js/console.log "DropdownMenu" DropdownMenu)
(js/console.log "DropdownToggle" DropdownToggle)
如果从 DropdownMenu
中删除 $default
,您会注意到日志行看起来与所有其他行不同,并且它是一个带有 default
属性.因此,您添加 $default
以使用 属性 并获得您实际需要的内容。
我正在尝试在重新构建项目中使用 react-bootstrap。我已经安装了 react-bootstrap with
npm install react-bootstrap
并像下面这样使用它的组件:
(:require
;; ...
["react-bootstrap/Button" :as Button]
;; ...
(defn main-panel []
[:div
[:> Button "Hit me"]
]])
一切正常,直到我尝试制作下拉菜单,更准确地说,直到我尝试使用 DropdownMenu
。我把它插入the example之后的打嗝的那一刻
[:> Dropdown
[:> DropdownToggle "button"]
[:> DropdownMenu {:variant :dark}
[:> DropdownItem "action1"]
[:> DropdownItem "action2"]
[:> DropdownItem "action3"]]]
我在浏览器控制台中得到以下信息:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
我对整个前端世界都非常陌生,所以我不确定是我做错了什么,还是 react-bootstrap、试剂或任何其他部分存在错误的项目。 这是这个问题的 MWE:https://github.com/lockie/react-bootstrap-cljs-demo
文档中有一节介绍如何 translate ES import
npm 包。
在那里你会发现 ["react-bootstrap/Button" :as Button]
应该是 ["react-bootstrap/Button$default" :as Button]
而不是(翻译 import Button from "react-bootstrap/Button";
)
但这仅在使用实际 ESM 代码时适用。然而,react-bootstrap
包是一个包含 ESM 和 CommonJS 的混合包。 shadow-cljs 在这种情况下默认情况下不会使用 ESM。
因此,一种选择是 shadow-cljs 使用 ESM 代码,方法是将其包含在构建配置中。
:js-options {:entry-keys ["module" "browser" "main"]}
这将需要为每个需求使用 $default
,因为它们都是默认导出。
另一种选择是使用默认的 CommonJS 代码。然而,这似乎打包不一致,这意味着大多数都能正常工作,但有一个例外。如果我将您的示例代码更改为
,它就可以正常工作(ns react-bootstrap-cljs-demo.views
(:require
[re-frame.core :as re-frame]
[react-bootstrap-cljs-demo.subs :as subs]
["react-bootstrap/Button" :as Button]
["react-bootstrap/Dropdown" :as Dropdown]
["react-bootstrap/DropdownItem" :as DropdownItem]
["react-bootstrap/DropdownMenu$default" :as DropdownMenu]
["react-bootstrap/DropdownToggle" :as DropdownToggle]
))
因此,只有 DropdownMenu
以需要 $default
的方式包含在内。似乎 react-bootstrap
方面可能存在疏忽或错误。 shadow-cljs
只是跟随磁盘上的内容。
选择哪种方法由您决定。使用 ESM 可能会导致其他软件包出现问题,或者可能工作得很好。一切都取决于您实际发布的包。
如何解决这个问题?
作为一个小指南:我通过记录所需的 :as
别名并在浏览器控制台中查看它来解决这个问题。
就这样
(ns react-bootstrap-cljs-demo.views
(:require
[re-frame.core :as re-frame]
[react-bootstrap-cljs-demo.subs :as subs]
["react-bootstrap/Button" :as Button]
["react-bootstrap/Dropdown" :as Dropdown]
["react-bootstrap/DropdownItem" :as DropdownItem]
["react-bootstrap/DropdownMenu$default" :as DropdownMenu]
["react-bootstrap/DropdownToggle" :as DropdownToggle]
))
(js/console.log "Button" Button)
(js/console.log "Dropdown" Dropdown)
(js/console.log "DropdownItem" DropdownItem)
(js/console.log "DropdownMenu" DropdownMenu)
(js/console.log "DropdownToggle" DropdownToggle)
如果从 DropdownMenu
中删除 $default
,您会注意到日志行看起来与所有其他行不同,并且它是一个带有 default
属性.因此,您添加 $default
以使用 属性 并获得您实际需要的内容。