Create closure type; allow async event handlers in props; allow short hand event handlers (#2437)

* create closure type; allow async event handlers in props; allow shorthand event handlers

* test forwarding event handlers with the shorthand syntax

* fix clippy

* fix imports in spawn async doctest
This commit is contained in:
Evan Almloff authored and GitHub committed 2024-06-10 18:47:07 -07:00
1 parent 79e18c2d62
commit d795995e20
11 files changed
+294 -103

No files matched your search

+22 -31
View File
@@ -25,16 +25,35 @@ macro_rules! impl_event {
#[doc(alias = $js_name)]
)?
#[inline]
pub fn $name<E: crate::EventReturn<T>, T>(mut _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'static) -> ::dioxus_core::Attribute {
pub fn $name<__Marker>(mut _f: impl ::dioxus_core::prelude::SuperInto<::dioxus_core::prelude::EventHandler<::dioxus_core::Event<$data>>, __Marker>) -> ::dioxus_core::Attribute {
let event_handler = _f.super_into();
::dioxus_core::Attribute::new(
impl_event!(@name $name $($js_name)?),
::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event<crate::PlatformEventData>| {
_f(e.map(|e|e.into())).spawn();
::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event<crate::PlatformEventData>| {
event_handler.call(e.map(|e| e.into()));
}),
None,
false,
).into()
}
#[doc(hidden)]
$( #[$attr] )*
pub mod $name {
use super::*;
// When expanding the macro, we use this version of the function if we see an inline closure to give better type inference
$( #[$attr] )*
pub fn call_with_explicit_closure<
__Marker,
Return: ::dioxus_core::SpawnIfAsync<__Marker> + 'static,
>(
event_handler: impl FnMut(::dioxus_core::Event<$data>) -> Return + 'static,
) -> ::dioxus_core::Attribute {
#[allow(deprecated)]
super::$name(event_handler)
}
}
)*
};
@@ -367,31 +386,3 @@ pub fn event_bubbles(evt: &str) -> bool {
}
}
}
#[doc(hidden)]
#[rustversion::attr(
since(1.78.0),
diagnostic::on_unimplemented(
message = "`EventHandlerReturn` is not implemented for `{Self}`",
label = "Return Value",
note = "Event handlers in dioxus need to return either: nothing (the unit type `()`), or an async block that dioxus will automatically spawn",
note = "You likely need to add a semicolon to the end of the event handler to make it return nothing",
)
)]
pub trait EventReturn<P>: Sized {
fn spawn(self) {}
}
impl EventReturn<()> for () {}
#[doc(hidden)]
pub struct AsyncMarker;
impl<T> EventReturn<AsyncMarker> for T
where
T: std::future::Future<Output = ()> + 'static,
{
#[inline]
fn spawn(self) {
dioxus_core::prelude::spawn(self);
}
}