widgetti / solara

A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps
https://solara.dev
MIT License
1.58k stars 103 forks source link

Input components are not `value_components` #48

Open Jhsmit opened 1 year ago

Jhsmit commented 1 year ago

I'm trying to use .connect on a solara.InputFloat, because I'm trying to adapt the scatter.py app example.

However, this is a solara.component, instead of a reacton.value_component. I was expecting the input components to also be value components because Checkbox, Select, Togglebuttons (togglebuttons is solara.value_component vs reacton.value_component.

Is there a reason these are not value components?

maartenbreddels commented 1 year ago

I simply have not finished it yet. However, we are considering an alternative strategy, which I demonstrate in https://github.com/widgetti/solara/pull/40/files

Basically, we went through this evolution

1) solara.SliderInt("Word limit", value=word_limit, on_value=set_word_limit, min=2, max=20) 2) solara.SliderInt("Word limit", min=2, max=20).connect(word_limit) 3) solara.SliderInt("Word limit", value=word_limit, min=2, max=20)

(where in 2 and 3 word_limit is a reactive variable).

The problem with 2, we noticed after a while is that it requires the component to have a value argument, that is not optional, which can lead to typing issues (Optional[int] vs int).

So, I'm considering moving to option (3), and deprecate the connect feature. Wondering what you think of it.

Jhsmit commented 1 year ago

Ah I see, Yes I noticed already that the State.logx.use() etc calls in scatter had disappeared in a newer version from the scatter example.

I do like the reactive variables, which is similar to the Holoviz panel mechanism of passing a param.String to a widget which then connects it.

I like the formalism of having some kind of State class with reactive variables, such as in the scatter and calculator examples when apps get bigger.

But I was just starting to get use to the use_state formalism, which is very nice for making smaller components UI where you want the state to be close to the declaration of the widgets in your code.

With (3), it would still be possible for users to use option 1? In cases when you have something that is not strictly value or simply want some other custom callback?

Will it be possible for users to make their own value_component components out of solara components?

maartenbreddels commented 1 year ago

The reactive variables lend themselves more to application state, the use_state lends itself more for creating reusable components (each components will have their own state).

So we are not removing support for one of the other, but since the primary focus of Solara is building apps, we plan to make the reactive variables more visible in the examples/quickstart/tutorial. When people want to create reusable components, the use_state (or maybe the use_reactive!) hooks comes into play. Does that make sense?

With (3), it would still be possible for users to use option 1?

Yes, it's gonna be a lot of Union[float, Reactive[float]] for us though :)

Will it be possible for users to make their own value_component components out of solara components?

With the new strategy, I don't think we 'need' the value_component any more (so no more .connect(..))

However, adding support for Reactive variables in your own components should be easy to do for users. Does that answer your questions?

Jhsmit commented 1 year ago

Yes that answers my questions.

With the new strategy, I don't think we 'need' the value_component any more (so no more .connect(..))

ah I see, yes that would make things a lot easier, so then the solar components would all have similar logic such as in the InputText in #40

It does make things a lot cleaner is the distinction 'value_component' / 'component' is no longer needed.

What would the calculator example look like if you would use a custom reactive class (such as on the docs/lab/toestand page to keep track of the state?

maartenbreddels commented 1 year ago

What would the calculator example look like if you would use a custom reactive class (such as on the docs/lab/toestand page to keep track of the state?

This is a very good question, and you are asking the right questions here!

I think it would be a good example to refactor this, but basically, each 'action' would be replaced by a method call, and the buttons would be attached to those event handlers.

The calculator example is the perfect example where simple 'two-way binding' is not enough, and you need to have events/methods that modify the state.