Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moved callback to leptos root and improved design #1795

Merged
merged 14 commits into from
Sep 29, 2023
Merged

Conversation

rambip
Copy link
Contributor

@rambip rambip commented Sep 27, 2023

This is a small update on callback.rs.

The most noticeable change is the location of the code: it moved to leptos because it may be usefull outside of the browser.
Another change: the suppression of HtmlCallback because now any HtmlElement implements Into<HtmlElement<AnyElement>>.

I wanted to implement Fn for the Callable trait, but 1) I was not able to do it because of unconstrained type parameters and 2) the call method on Callable is the same as the call method on Fn, this is a bit dumb ...

It would be really cool if this change could be accepted for 5.0, just for the fact that HtmlCallback and ViewCallback will never exist.

@gbj
Copy link
Collaborator

gbj commented Sep 27, 2023

Thanks so much. I will definitely review before releasing 0.5.

@gbj
Copy link
Collaborator

gbj commented Sep 27, 2023

@rambip I'm curious to hear what you think of this one, which does implement Fn for Callback: ccef384

Using the Tuple trait here means you can call it like a normal function. This compiles and works as expected:

#[component]
fn MyComponent(#[prop(into)] render_number: Callback<(i32, i32), String>) -> impl IntoView {
    view! {
        <div>
            {render_number(42, 37)}
            // does the same thing
            {render_number.call((42, 37))}
        </div>
    }
}

#[component]
pub fn App() -> impl IntoView {
    view! {
        <MyComponent render_number=|(x, y)| format!("x: {x} - y: {y}")/>
    }
}

@rambip
Copy link
Contributor Author

rambip commented Sep 28, 2023

@rambip I'm curious to hear what you think of this one, which does implement Fn for Callback: ccef384

Using the Tuple trait here means you can call it like a normal function. This compiles and works as expected:

#[component]
fn MyComponent(#[prop(into)] render_number: Callback<(i32, i32), String>) -> impl IntoView {
    view! {
        <div>
            {render_number(42, 37)}
            // does the same thing
            {render_number.call((42, 37))}
        </div>
    }
}

#[component]
pub fn App() -> impl IntoView {
    view! {
        <MyComponent render_number=|(x, y)| format!("x: {x} - y: {y}")/>
    }
}

I didn't manage to implement Fn for Callback, thank's ! I got an error saying it cannot disambiguate betwen Callable::call and Fn::call 🤔

Please implement it for StoredValue<Callback> too !

That said, It can be very counter-intuitive for users to write Callback<(i32,) -> String>; I already thought about that.
Packing arguments into a tuple and calling with a tuple seems to be better for me (meaning implementing Fn only for a 1-Tuple). In addition, if the user wants a callback with 0 arguments, he should use Into<Signal>, (see #1722) instead (maybe we should add that in the module docs too)

@gbj
Copy link
Collaborator

gbj commented Sep 28, 2023

I switched back to the more obvious Fn implementation.

Fn can't be implemented on StoredCallback unless StoredCallback is its own struct and not a type alias, for two reasons

  1. orphan rules: StoredValue isn't implemented in leptos, it's in leptos_reactive, and we can't implement a trait from A on a struct from B in crate C
  2. StoredValue already implements Fn IIRC

@rambip
Copy link
Contributor Author

rambip commented Sep 28, 2023

I switched back to the more obvious Fn implementation.

Fn can't be implemented on StoredCallback unless StoredCallback is its own struct and not a type alias, for two reasons

  1. orphan rules: StoredValue isn't implemented in leptos, it's in leptos_reactive, and we can't implement a trait from A on a struct from B in crate C
  2. StoredValue already implements Fn IIRC

Could Callback be defined in leptos_reactive and be defined as StoredValue<Box<dyn Fn>> ?
That would be way simpler to use ...

@rambip
Copy link
Contributor Author

rambip commented Sep 28, 2023

I wrote it !
The only thing I had to add is In: 'static and Out: 'static basically.
I don't know what that means exactly to be honnest but I don't think that's an issue.

@gbj gbj merged commit bd4d220 into leptos-rs:main Sep 29, 2023
33 checks passed
@lpotthast
Copy link
Contributor

Nice changes! The callback type is basically back to its last state in leptonic. I would say as well that the "every callback is a stored vlaue and therefore copy" approach is the most ergonomic for all users. You immediately run into compiler errors if you try to use a non-copy callback in more than one place. But wasn't there a discussion about not storing each callback as a stored value for performance reasons? Did some preconditions change in 0.5 or am I wrong and this was generally deemed ok?

@gbj
Copy link
Collaborator

gbj commented Oct 5, 2023

But wasn't there a discussion about not storing each callback as a stored value for performance reasons? Did some preconditions change in 0.5 or am I wrong and this was generally deemed ok?

Enough people argued against me and the difference is small enough that I just gave in 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants