I’m struggling to use the ReactComponent, because I don’t understand how the bundling is supposed to work. I’ve been reading and re-reading the bundling guide, but there doesn’t seem to be a fully functioning example for react.
I have:
# confetti.py
import panel as pn
from panel.custom import ReactComponent
pn.extension()
class Confetti(ReactComponent):
_bundle = './ConfettiButton.bundle.js'
Confetti().servable()
and
// index.js
import { Confetti } from "./confetti";
import * as React from "react";
import { createRoot } from "react-dom/client";
export default { Confetti, React, createRoot };
package.js
{
"name": "confetti-button",
"dependencies": {
"canvas-confetti": "^1.6.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
}
}
confetti.jsx
import confetti from "canvas-confetti";
export function Confetti() {
return <h1>Hi</h1>;
}
I then run:
esbuild index.js --bundle --format=esm --outfile=ConfettiButton.bundle.js
and
panel serve confetti.py
But get:
[bokeh 3.6.1] setting log level to: 'info'
bokeh.min.js?v=ab343bc1ea96aa3f04b4b7cc078b778826644f535553eabf00ca2afa504963f0a3b97f72c264d666877921765e160c8a5e75723c10651502c44946ae398026aa:234 [bokeh 3.6.1] Websocket connection 0 is now open
bokeh.min.js?v=ab343bc1ea96aa3f04b4b7cc078b778826644f535553eabf00ca2afa504963f0a3b97f72c264d666877921765e160c8a5e75723c10651502c44946ae398026aa:166 [bokeh 3.6.1] document idle at 214 ms
bokeh.min.js?v=ab343bc1ea96aa3f04b4b7cc078b778826644f535553eabf00ca2afa504963f0a3b97f72c264d666877921765e160c8a5e75723c10651502c44946ae398026aa:164 Bokeh items were rendered successfully
ConfettiButton.bundle.js:158 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Component`. Error Component Stack
at Component (c0eff922-dae3-4ef3-921b-eb702f1f515f:126:1)
overrideMethod @ hook.js:608
printWarning @ ConfettiButton.bundle.js:158
error @ ConfettiButton.bundle.js:142
createElementWithValidation @ ConfettiButton.bundle.js:1608
render @ c0eff922-dae3-4ef3-921b-eb702f1f515f:134
finishClassComponent @ ConfettiButton.bundle.js:16652
updateClassComponent @ ConfettiButton.bundle.js:16617
beginWork @ ConfettiButton.bundle.js:17883
beginWork$1 @ ConfettiButton.bundle.js:21711
performUnitOfWork @ ConfettiButton.bundle.js:21156
workLoopSync @ ConfettiButton.bundle.js:21095
renderRootSync @ ConfettiButton.bundle.js:21074
performConcurrentWorkOnRoot @ ConfettiButton.bundle.js:20633
workLoop @ ConfettiButton.bundle.js:2102
flushWork @ ConfettiButton.bundle.js:2081
performWorkUntilDeadline @ ConfettiButton.bundle.js:2289
Show 1 more frame
Show less
ConfettiButton.bundle.js:158 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Component`. Error Component Stack
at Component (c0eff922-dae3-4ef3-921b-eb702f1f515f:126:1)
overrideMethod @ hook.js:608
printWarning @ ConfettiButton.bundle.js:158
error @ ConfettiButton.bundle.js:142
createElementWithValidation @ ConfettiButton.bundle.js:1608
render @ c0eff922-dae3-4ef3-921b-eb702f1f515f:134
finishClassComponent @ ConfettiButton.bundle.js:16652
updateClassComponent @ ConfettiButton.bundle.js:16617
beginWork @ ConfettiButton.bundle.js:17883
callCallback2 @ ConfettiButton.bundle.js:5585
invokeGuardedCallbackDev @ ConfettiButton.bundle.js:5610
invokeGuardedCallback @ ConfettiButton.bundle.js:5644
beginWork$1 @ ConfettiButton.bundle.js:21723
performUnitOfWork @ ConfettiButton.bundle.js:21156
workLoopSync @ ConfettiButton.bundle.js:21095
renderRootSync @ ConfettiButton.bundle.js:21074
performConcurrentWorkOnRoot @ ConfettiButton.bundle.js:20633
workLoop @ ConfettiButton.bundle.js:2102
flushWork @ ConfettiButton.bundle.js:2081
performWorkUntilDeadline @ ConfettiButton.bundle.js:2289
Show 1 more frame
Show less
ConfettiButton.bundle.js:22405 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Component`.
at createFiberFromTypeAndProps (ConfettiButton.bundle.js:22405:23)
at createFiberFromElement (ConfettiButton.bundle.js:22426:23)
at reconcileSingleElement (ConfettiButton.bundle.js:12465:31)
at reconcileChildFibers2 (ConfettiButton.bundle.js:12502:43)
at reconcileChildren (ConfettiButton.bundle.js:16243:37)
at finishClassComponent (ConfettiButton.bundle.js:16671:13)
at updateClassComponent (ConfettiButton.bundle.js:16617:32)
at beginWork (ConfettiButton.bundle.js:17883:22)
at HTMLUnknownElement.callCallback2 (ConfettiButton.bundle.js:5585:22)
at Object.invokeGuardedCallbackDev (ConfettiButton.bundle.js:5610:24)
createFiberFromTypeAndProps @ ConfettiButton.bundle.js:22405
createFiberFromElement @ ConfettiButton.bundle.js:22426
reconcileSingleElement @ ConfettiButton.bundle.js:12465
reconcileChildFibers2 @ ConfettiButton.bundle.js:12502
reconcileChildren @ ConfettiButton.bundle.js:16243
finishClassComponent @ ConfettiButton.bundle.js:16671
updateClassComponent @ ConfettiButton.bundle.js:16617
beginWork @ ConfettiButton.bundle.js:17883
callCallback2 @ ConfettiButton.bundle.js:5585
invokeGuardedCallbackDev @ ConfettiButton.bundle.js:5610
invokeGuardedCallback @ ConfettiButton.bundle.js:5644
beginWork$1 @ ConfettiButton.bundle.js:21723
performUnitOfWork @ ConfettiButton.bundle.js:21156
workLoopSync @ ConfettiButton.bundle.js:21095
renderRootSync @ ConfettiButton.bundle.js:21074
performConcurrentWorkOnRoot @ ConfettiButton.bundle.js:20633
workLoop @ ConfettiButton.bundle.js:2102
flushWork @ ConfettiButton.bundle.js:2081
performWorkUntilDeadline @ ConfettiButton.bundle.js:2289
Any idea how to get this working? This example is obviously very simple, but I want to break out of writing typescript within a python file… not really the same thing.