diff --git a/crates/react-html/src/macros/props.rs b/crates/react-html/src/macros/props.rs
index 49d49311..a7da62f2 100644
--- a/crates/react-html/src/macros/props.rs
+++ b/crates/react-html/src/macros/props.rs
@@ -13,8 +13,8 @@ macro_rules! __impl_prop_default {
{ event_handler }
) => {
$($attr)*
- fn $k (mut self, event_handler: Option>) -> Self
- where react::WrapFn: react::event::IntoJsEventHandler<$v_ty>
+ fn $k (mut self, event_handler: Option>) -> Self
+ where react::AnyFn: react::event::IntoJsEventHandler<$v_ty>
{
if let Some(event_handler) = event_handler {
let ret = react::event::IntoJsEventHandler::into_js_event_handler(event_handler);
diff --git a/crates/react/src/any_fn_family/any_fn.rs b/crates/react/src/any_fn_family/any_fn.rs
new file mode 100644
index 00000000..99f8ac56
--- /dev/null
+++ b/crates/react/src/any_fn_family/any_fn.rs
@@ -0,0 +1,125 @@
+use std::{any::Any, rc::Rc};
+use wasm_bindgen::closure::{Closure, WasmClosure};
+
+use crate::{DynFn, FnOfArgs, IntoPropValue};
+
+pub struct AnyFn(pub Rc)
+where
+ F: ?Sized + DynFn;
+
+impl AnyFn {
+ #[inline]
+ pub fn inner(&self) -> &Rc {
+ &self.0
+ }
+
+ #[inline]
+ pub fn into_inner(self) -> Rc {
+ self.0
+ }
+
+ #[inline]
+ pub fn new<
+ TFunc: 'static + ?Sized + FnOfArgs,
+ RF: crate::IntoRc,
+ >(
+ func: RF,
+ ) -> Self {
+ let func: Rc = func.into_rc();
+ let func = func.into_rc_dyn_fn();
+ Self(func)
+ }
+}
+
+impl std::ops::Deref for AnyFn {
+ type Target = Rc;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl AsRef> for AnyFn {
+ #[inline]
+ fn as_ref(&self) -> &Rc {
+ &self.0
+ }
+}
+
+impl Clone for AnyFn {
+ #[inline]
+ fn clone(&self) -> Self {
+ Self(self.0.clone())
+ }
+}
+
+impl std::fmt::Debug for AnyFn {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "AnyFn<{}>", std::any::type_name::())
+ }
+}
+
+impl crate::SafeIntoJsRuntime for AnyFn
+where
+ F: 'static + WasmClosure,
+{
+ fn safe_into_js_runtime(self) -> crate::PassedToJsRuntime {
+ let boxed = self.0.rc_into_box_dyn_fn();
+
+ let closure = Closure::wrap(boxed);
+ let js_value = closure.as_ref().clone();
+ crate::PassedToJsRuntime {
+ js_value,
+ to_persist: Some(Box::new(closure) as Box),
+ }
+ }
+}
+
+impl>
+ IntoPropValue> for Rc
+{
+ fn into_prop_value(self) -> AnyFn {
+ AnyFn(self.into_rc_dyn_fn())
+ }
+}
+
+impl>
+ IntoPropValue