widgetti / ipyreact

React for ipywidgets that just works. No webpack, no npm, no hassle
BSD 3-Clause "New" or "Revised" License
119 stars 8 forks source link

Widget does not show anymore after restarting jupyterlab server #40

Closed kolibril13 closed 1 year ago

kolibril13 commented 1 year ago

When I save a notebook with a rendered ipyreact output and then restart the jupyterlab server, the widget does not show anymore. It would be really amazing if this was possible!

image

here is a minimal example for testing:

import ipyreact
from traitlets import Unicode

class QRCodeWidget(ipyreact.ReactWidget):
    content = Unicode("").tag(sync=True)
    _esm = """
    import React from "react";
    import QRCode from "react-qr-code";

    export default function App({ content }) {
      return <QRCode value={content} />
    }
    """

q = QRCodeWidget(content="Hello World")
q
maartenbreddels commented 1 year ago

Hi Jan-Hendrik,

What you need to do is embed the widget state into the notebook (which is not enabled by default). Classic notebook and lab have that under different parts of the UI.

Regards,

Maarten

kolibril13 commented 1 year ago

Hi Maarten, Thanks for your quick response! I found the option "save widget state automatically" in the jupyter GUI" and enabled it. Before enabling that feature, there's no error in the console when saving the notebook. However, when I enable this feature and then save the notebook, I get the following error message in the console. Any ideas? :)

image
jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1 TypeError: this._context.model.metadata.set is not a function
    at f._saveState (134.402424ef4079078b2e0e.js?v=402424ef4079078b2e0e:1:77341)
    at 134.402424ef4079078b2e0e.js?v=402424ef4079078b2e0e:1:77235
    at m (jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1:1646609)
    at Object.l [as emit] (jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1:1646285)
    at a.emit (jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1:1644122)
    at h._save (jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1:585825)
    at h.save (jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1:581361)
    at async execute (jlab_core.f68a597bc4700114bad4.js?v=f68a597bc4700114bad4:1:552929)
maartenbreddels commented 1 year ago

That seems like a bug in ipywidgets, the lab widget manager. Which version are you in? Do you want to check if this is reported at https://github.com/jupyter-widgets/ipywidgets already?

And, does it work nonetheless, or is it broken?

kolibril13 commented 1 year ago

I'm in JupyterLab Version 4.0.2. And you're right, this TypeError: this._context.model.metadata.set is not a function is unrelated to ipyreact and comes also when I save a notebook that does not contain any widget at all.

Do you want to check if this is reported at https://github.com/jupyter-widgets/ipywidgets already?

I've just checked, and no, this is not yet reported. Should I make a report?

Regarding ipyreact: unfortunately yes, after restating the kernel and reopening the notebook, I still see the message: Error displaying widget: model not found One further observation: When I restart the kernel, this red icon appears next to the widget

image
maartenbreddels commented 1 year ago

Yes, that means that the widget is not connected to the kernel.

Should I make a report?

Yes please :) Did you check if it works in jlab 3.6?

kolibril13 commented 1 year ago

I just did

python3.10 -m venv .venv
source .venv/bin/activate
pip install jupyterlab==3.6
pip install ipyreact

and tested it, but still same error:

image

Yes please :)

sure, I'll create that issue! :)

kolibril13 commented 1 year ago

Some more infos after some more testing: in JupyterLab 3.6 with "save widget state automatically" enabled, the TypeError: this._context.model.metadata.set is not a function does not occur.

Also, this is the error message when reopening the notebook in 3.6:

image
kolibril13 commented 1 year ago

And one more observation: The same issue happens also with anywidget, both in jlab 3.6 and jlab 4.0.2

image
import anywidget
import traitlets

class CounterWidget(anywidget.AnyWidget):
    count = traitlets.Int(0).tag(sync=True)
    _esm = """
    export function render({ model, el }) {
      let getCount = () => model.get("count");
      let button = document.createElement("button");
      button.innerHTML = `count is ${getCount()}`;
      button.addEventListener("click", () => {
        model.set("count", getCount() + 1);
        model.save_changes();
      });
      model.on("change:count", () => {
        button.innerHTML = `count is ${getCount()}`;
      });
      el.appendChild(button);
    }
    """
c = CounterWidget()
c
kolibril13 commented 1 year ago

I just did some more testing. Here is now the most minimal example to reproduce this problem, together with the exact error message:

I run this below example, restart the kernel, and then close and reopen the notebook.

import ipyreact

class MyExampleWidget(ipyreact.ReactWidget):
    _esm = """
    import * as React from "react";
    export default function MyButton() {
        return < button > X < /button> 
    };"""

MyExampleWidget()

the output will then say: Error displaying widget: model not found

and the error in the console will say:

134.402424ef4079078b2e0e.js?v=402424ef4079078b2e0e:1 Error: widget model not found
    at f.get_model (150.1a6d6a3a0542a41bec5a.js?v=1a6d6a3a0542a41bec5a:1:3461)
    at w.renderModel (134.402424ef4079078b2e0e.js?v=402424ef4079078b2e0e:1:72019)
kolibril13 commented 1 year ago

Just noted that this is not an ipyreact issue. This ipywidget code will lead to the same error when reopening the notebook:

import ipywidgets as widgets

widgets.Button(description="Click Me!")
widgets.IntSlider(0,10)

I've both tested it in Jlab 4 and Jlab 3.5, both times the same error

image
kolibril13 commented 1 year ago

Closing this, as it's not an ipyreact issue.