widgetti / ipyreact

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

Example on how to pass a python object into ReactWidget #17

Open kolibril13 opened 1 year ago

kolibril13 commented 1 year ago

I have a python object of type fig. This fig is used to initialize the ReactWidget. In the init function, the figure is processed to a string and then later used in the my_message traitlet.

Here is an example on how I would do that: Question: is this a best practice solution that we could provide in the docs like this?

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 2))
ax.plot([1,2], [10,20], c = "orange");

###

import ipyreact
from traitlets import Unicode

class TldrawWidget(ipyreact.ReactWidget):
    def __init__(self,my_figure= None, **kwargs):

        my_str = f"the size of the figure is {my_figure.get_size_inches()}"

        super().__init__(**kwargs, my_message=my_str)

    my_message = Unicode("").tag(sync=True) 
    _esm = """
    import * as React from "react";

    export default function MyButton({my_message}) {
        return < button > {my_message} < /button> 
    };"""

TldrawWidget(my_figure=fig)
maartenbreddels commented 1 year ago

The most traitlets correct way of doing this would be:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 2))
ax.plot([1,2], [10,20], c = "orange");

###

import ipyreact
from traitlets import Unicode, Any, observe, default

class TldrawWidget(ipyreact.ReactWidget):
    fig = Any()
    my_message = Unicode("").tag(sync=True) 

    @default('my_message')
    def _my_message(self):
        return f"the size of the figure is {fig.get_size_inches()}"

    @observe("fig")
    def _fig_change(self, change):
        self.my_message = self._my_message()

    _esm = """
    import * as React from "react";

    export default function MyButton({my_message}) {
        return < button > {my_message} < /button> 
    };"""

TldrawWidget(my_figure=fig)

See

I don't like having to define both the default and the observe personally. In Solara we will implement this using reactive variables that auto update based on its dependencies, but this would be the traitlets way :)

Please close if this answers your question! Otherwise I'm happy to help again