wrapped callbacks in non-reactive zones to remove potential warnings

This commit is contained in:
Maccesch 2024-02-27 00:02:37 +00:00
parent 446b10b1cf
commit 7216a3281c
21 changed files with 279 additions and 40 deletions

View file

@ -3,6 +3,12 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] -
### Changes 🔥
- Wrapped callbacks in a non-reactive zone to remove potential warnings.
## [0.10.3] - 2024-02-23
### New Functions 🚀

View file

@ -107,9 +107,13 @@ where
F: FnMut(web_sys::Event) + Clone + 'static,
I: Into<web_sys::EventTarget> + Clone + 'static,
{
cfg_if! { if #[cfg(feature = "ssr")] {
#[cfg(feature = "ssr")]
{
|| {}
} else {
}
#[cfg(not(feature = "ssr"))]
{
let OnClickOutsideOptions {
ignore,
capture,
@ -163,7 +167,8 @@ where
if let Some(el) = target.get_untracked() {
let el = el.into();
if el == event_target(&event) || event.composed_path().includes(el.as_ref(), 0) {
if el == event_target(&event) || event.composed_path().includes(el.as_ref(), 0)
{
return;
}
@ -176,7 +181,13 @@ where
return;
}
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
handler(event.into());
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
}
};
@ -251,7 +262,7 @@ where
f();
}
}
}}
}
}
/// Options for [`on_click_outside_with_options`].

View file

@ -134,12 +134,22 @@ where
x: event.client_x() as f64 - rect.left(),
y: event.client_y() as f64 - rect.top(),
};
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
if !on_start(UseDraggableCallbackArgs {
position,
event: event.clone(),
}) {
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
return;
}
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_start_position.set(Some(position));
handle_event(event);
}
@ -159,10 +169,18 @@ where
y: event.client_y() as f64 - start_position.y,
};
set_position.set(position);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_move(UseDraggableCallbackArgs {
position,
event: event.clone(),
});
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
handle_event(event);
}
}
@ -176,10 +194,18 @@ where
return;
}
set_start_position.set(None);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_end(UseDraggableCallbackArgs {
position: position.get_untracked(),
event: event.clone(),
});
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
handle_event(event);
};

View file

@ -74,7 +74,8 @@ where
let (is_over_drop_zone, set_over_drop_zone) = create_signal(false);
let (files, set_files) = create_signal(Vec::<web_sys::File>::new());
cfg_if! { if #[cfg(not(feature = "ssr"))] {
#[cfg(not(feature = "ssr"))]
{
let UseDropZoneOptions {
on_drop,
on_enter,
@ -105,19 +106,32 @@ where
update_files(&event);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_enter(UseDropZoneEvent {
files: files.get_untracked(),
event,
});
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
});
let _ = use_event_listener(target.clone(), dragover, move |event| {
event.prevent_default();
update_files(&event);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_over(UseDropZoneEvent {
files: files.get_untracked(),
event,
});
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
});
let _ = use_event_listener(target.clone(), dragleave, move |event| {
@ -129,10 +143,16 @@ where
update_files(&event);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_leave(UseDropZoneEvent {
files: files.get_untracked(),
event,
});
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
});
let _ = use_event_listener(target, drop, move |event| {
@ -142,12 +162,18 @@ where
update_files(&event);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_drop(UseDropZoneEvent {
files: files.get_untracked(),
event,
});
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
});
}}
}
UseDropZoneReturn {
files: files.into(),

View file

@ -70,10 +70,11 @@ where
let update = move || ();
} else {
use leptos::ev::{resize, scroll};
use crate::{
use_event_listener_with_options, use_resize_observer, use_window, UseEventListenerOptions,
use_event_listener_with_options, use_resize_observer, use_window,
UseEventListenerOptions,
};
use leptos::ev::{resize, scroll};
let UseElementBoundingOptions {
reset,

View file

@ -102,7 +102,7 @@ where
pub fn use_event_listener_with_options<Ev, El, T, F>(
target: El,
event: Ev,
handler: F,
mut handler: F,
options: UseEventListenerOptions,
) -> impl Fn() + Clone
where
@ -111,11 +111,24 @@ where
T: Into<web_sys::EventTarget> + Clone + 'static,
F: FnMut(<Ev as EventDescriptor>::EventType) + 'static,
{
cfg_if! { if #[cfg(feature = "ssr")] {
#[cfg(feature = "ssr")]
{
|| {}
} else {
}
#[cfg(not(feature = "ssr"))]
{
let event_name = event.name();
let closure_js = Closure::wrap(Box::new(handler) as Box<dyn FnMut(_)>).into_js_value();
let closure_js = Closure::wrap(Box::new(move |e| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
handler(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}) as Box<dyn FnMut(_)>)
.into_js_value();
let cleanup_fn = {
let closure_js = closure_js.clone();
@ -158,7 +171,8 @@ where
if let Some(element) = element {
let options = options.as_add_event_listener_options();
_ = element.add_event_listener_with_callback_and_add_event_listener_options(
_ = element
.add_event_listener_with_callback_and_add_event_listener_options(
&event_name,
closure_js.as_ref().unchecked_ref(),
&options,
@ -177,7 +191,7 @@ where
on_cleanup(stop.clone());
stop
}}
}
}
/// Options for [`use_event_listener_with_options`].

View file

@ -157,11 +157,17 @@ where
let measure = measure.clone();
spawn_local(async move {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
join!(
on_load_more.with_value(|f| f(state)),
sleep(Duration::from_millis(interval as u64))
);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_loading.set(false);
sleep(Duration::ZERO).await;
measure();

View file

@ -100,6 +100,9 @@ where
} else {
let closure_js = Closure::<dyn FnMut(js_sys::Array, web_sys::IntersectionObserver)>::new(
move |entries: js_sys::Array, observer| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback(
entries
.to_vec()
@ -108,11 +111,15 @@ where
.collect(),
observer,
);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
},
)
.into_js_value();
let observer: Rc<RefCell<Option<web_sys::IntersectionObserver>>> = Rc::new(RefCell::new(None));
let observer: Rc<RefCell<Option<web_sys::IntersectionObserver>>> =
Rc::new(RefCell::new(None));
let cleanup = {
let obsserver = Rc::clone(&observer);

View file

@ -1,7 +1,6 @@
#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports))]
use crate::utils::Pausable;
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::leptos_dom::helpers::IntervalHandle;
use leptos::*;
@ -89,7 +88,8 @@ where
let interval = interval.into();
let resume = move || {
cfg_if! { if #[cfg(not(feature = "ssr"))] {
#[cfg(not(feature = "ssr"))]
{
let interval_value = interval.get();
if interval_value == 0 {
return;
@ -97,15 +97,30 @@ where
set_active.set(true);
let callback = {
let callback = callback.clone();
move || {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback();
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
};
if immediate_callback {
callback.clone()();
}
clean();
timer.set(
set_interval_with_handle(callback.clone(), Duration::from_millis(interval_value)).ok(),
set_interval_with_handle(callback.clone(), Duration::from_millis(interval_value))
.ok(),
);
}}
}
};
if immediate {

View file

@ -73,16 +73,23 @@ where
T: Into<web_sys::Element> + Clone + 'static,
F: FnMut(Vec<web_sys::MutationRecord>, web_sys::MutationObserver) + 'static,
{
cfg_if! { if #[cfg(feature = "ssr")] {
#[cfg(feature = "ssr")]
{
UseMutationObserverReturn {
is_supported: Signal::derive(|| true),
stop: || {},
}
} else {
}
#[cfg(not(feature = "ssr"))]
{
use crate::js;
let closure_js = Closure::<dyn FnMut(js_sys::Array, web_sys::MutationObserver)>::new(
move |entries: js_sys::Array, observer| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback(
entries
.to_vec()
@ -91,6 +98,9 @@ where
.collect(),
observer,
);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
},
)
.into_js_value();
@ -122,7 +132,8 @@ where
cleanup();
if is_supported.get() && !targets.is_empty() {
let obs = web_sys::MutationObserver::new(closure_js.as_ref().unchecked_ref())
let obs =
web_sys::MutationObserver::new(closure_js.as_ref().unchecked_ref())
.expect("failed to create MutationObserver");
for target in targets.iter().flatten() {
@ -145,7 +156,7 @@ where
on_cleanup(stop.clone());
UseMutationObserverReturn { is_supported, stop }
}}
}
}
/// Options for [`use_mutation_observer_with_options`].

View file

@ -100,8 +100,14 @@ pub fn use_raf_fn_with_options(
0.0
};
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback(UseRafFnCallbackArgs { delta, timestamp });
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
previous_frame_timestamp.set(timestamp);
request_next_frame();

View file

@ -89,6 +89,9 @@ where
let closure_js = Closure::<dyn FnMut(js_sys::Array, web_sys::ResizeObserver)>::new(
move |entries: js_sys::Array, observer| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback(
entries
.to_vec()
@ -97,6 +100,9 @@ where
.collect(),
observer,
);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
},
)
.into_js_value();

View file

@ -331,7 +331,9 @@ where
let top = scroll_top_abs <= offset.top;
let bottom = scroll_top_abs + target.client_height() as f64
>= target.scroll_height() as f64 - offset.bottom - ARRIVED_STATE_THRESHOLD_PIXELS;
>= target.scroll_height() as f64
- offset.bottom
- ARRIVED_STATE_THRESHOLD_PIXELS;
// reverse columns and rows behave exactly the other way around,
// bottom is treated as top and top is treated as the negative version of bottom
@ -357,6 +359,7 @@ where
set_arrived_state(target);
set_is_scrolling.set(true);
on_scroll_end_debounced.clone()(e.clone());
on_scroll.clone()(e);
}

View file

@ -50,7 +50,13 @@ pub fn use_service_worker_with_options(
if let Some(navigator) = use_window().navigator() {
let on_controller_change = options.on_controller_change.clone();
let js_closure = Closure::wrap(Box::new(move |_event: JsValue| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_controller_change();
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}) as Box<dyn FnMut(JsValue)>)
.into_js_value();
navigator

View file

@ -81,7 +81,13 @@ where
set_pending.set(false);
timer.set(None);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback(arg);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
},
Duration::from_millis(delay.get_untracked() as u64),

View file

@ -84,7 +84,14 @@ pub fn use_timestamp_with_controls_and_options(options: UseTimestampOptions) ->
move || {
update();
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
callback(ts.get_untracked());
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
};

View file

@ -71,7 +71,13 @@ pub fn use_web_notification_with_options(
let on_click_closure = Closure::<dyn Fn(web_sys::Event)>::new({
let on_click = Rc::clone(&options.on_click);
move |e: web_sys::Event| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_click(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
})
.into_js_value();
@ -79,7 +85,13 @@ pub fn use_web_notification_with_options(
let on_close_closure = Closure::<dyn Fn(web_sys::Event)>::new({
let on_close = Rc::clone(&options.on_close);
move |e: web_sys::Event| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_close(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
})
.into_js_value();
@ -87,7 +99,13 @@ pub fn use_web_notification_with_options(
let on_error_closure = Closure::<dyn Fn(web_sys::Event)>::new({
let on_error = Rc::clone(&options.on_error);
move |e: web_sys::Event| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_error(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
})
.into_js_value();
@ -95,7 +113,13 @@ pub fn use_web_notification_with_options(
let on_show_closure = Closure::<dyn Fn(web_sys::Event)>::new({
let on_show = Rc::clone(&options.on_show);
move |e: web_sys::Event| {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_show(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
}
})
.into_js_value();

View file

@ -77,7 +77,8 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
/// ## Relative Paths
///
/// If the provided `url` is relative, it will be resolved relative to the current page.
/// Urls will be resolved like this:
/// Urls will be resolved like this the following. Please note that the protocol (http vs https) will
/// be taken into account as well.
///
/// | Current Page | Relative Url | Resolved Url |
/// |--------------------------------|--------------------------|-------------------------------------|
@ -237,8 +238,8 @@ pub fn use_websocket_with_options(
let connect_ref: StoredValue<Option<Rc<dyn Fn()>>> = store_value(None);
cfg_if! { if #[cfg(not(feature = "ssr"))] {
#[cfg(not(feature = "ssr"))]
{
let reconnect_ref: StoredValue<Option<Rc<dyn Fn()>>> = store_value(None);
reconnect_ref.set_value({
let ws = ws_ref.get_value();
@ -301,10 +302,17 @@ pub fn use_websocket_with_options(
return;
}
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_open(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_ready_state.set(ConnectionReadyState::Open);
}) as Box<dyn FnMut(Event)>);
})
as Box<dyn FnMut(Event)>);
web_socket.set_onopen(Some(onopen_closure.as_ref().unchecked_ref()));
// Forget the closure to keep it alive
onopen_closure.forget();
@ -325,12 +333,22 @@ pub fn use_websocket_with_options(
|_| {
e.data().dyn_into::<js_sys::JsString>().map_or_else(
|_| {
unreachable!("message event, received Unknown: {:?}", e.data());
unreachable!(
"message event, received Unknown: {:?}",
e.data()
);
},
|txt| {
let txt = String::from(&txt);
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_message(txt.clone());
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_message.set(Some(txt));
},
);
@ -338,8 +356,15 @@ pub fn use_websocket_with_options(
|array_buffer| {
let array = js_sys::Uint8Array::new(&array_buffer);
let array = array.to_vec();
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_message_bytes(array.clone());
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_message_bytes.set(Some(array));
},
);
@ -363,10 +388,17 @@ pub fn use_websocket_with_options(
reconnect();
}
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_error(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_ready_state.set(ConnectionReadyState::Closed);
}) as Box<dyn FnMut(Event)>);
})
as Box<dyn FnMut(Event)>);
web_socket.set_onerror(Some(onerror_closure.as_ref().unchecked_ref()));
onerror_closure.forget();
}
@ -385,8 +417,14 @@ pub fn use_websocket_with_options(
reconnect();
}
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
on_close(e);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
set_ready_state.set(ConnectionReadyState::Closed);
})
as Box<dyn FnMut(CloseEvent)>);
@ -397,7 +435,7 @@ pub fn use_websocket_with_options(
ws_ref.set_value(Some(web_socket));
}))
});
}}
}
// Send text (String)
let send = {

View file

@ -3,7 +3,7 @@
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::leptos_dom::helpers::TimeoutHandle;
use leptos::{on_cleanup, set_timeout_with_handle, MaybeSignal, SignalGetUntracked};
use leptos::*;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use std::time::Duration;
@ -51,8 +51,14 @@ where
let last_return_val = Rc::clone(&last_return_value);
let invoke = move || {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
let return_value = _invoke();
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
let mut val_mut = last_return_val.borrow_mut();
*val_mut = Some(return_value);
};

View file

@ -4,7 +4,7 @@ use crate::core::now;
use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::leptos_dom::helpers::TimeoutHandle;
use leptos::{on_cleanup, set_timeout_with_handle, MaybeSignal, SignalGetUntracked};
use leptos::*;
use std::cell::{Cell, RefCell};
use std::cmp::max;
use std::rc::Rc;
@ -57,8 +57,14 @@ where
let last_return_val = Rc::clone(&last_return_value);
let invoke = move || {
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
let return_value = _invoke();
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
let mut val_mut = last_return_val.borrow_mut();
*val_mut = Some(return_value);
};

View file

@ -111,14 +111,22 @@ where
let prev_callback_val = Rc::clone(&prev_callback_value);
move || {
callback(
#[cfg(debug_assertions)]
let prev = SpecialNonReactiveZone::enter();
let ret = callback(
cur_deps_value
.borrow()
.as_ref()
.expect("this will not be called before there is deps value"),
prev_deps_value.borrow().as_ref(),
prev_callback_val.take(),
)
);
#[cfg(debug_assertions)]
SpecialNonReactiveZone::exit(prev);
ret
}
};