mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-03-13 01:09:48 -04:00
fixed use_event_listener removing of listener with non default options
This commit is contained in:
parent
413a6f933e
commit
fa47bab2cd
3 changed files with 162 additions and 158 deletions
|
@ -28,6 +28,7 @@ wasm-bindgen-futures = "0.4"
|
||||||
[dependencies.web-sys]
|
[dependencies.web-sys]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
features = [
|
features = [
|
||||||
|
"AddEventListenerOptions",
|
||||||
"BinaryType",
|
"BinaryType",
|
||||||
"CssStyleDeclaration",
|
"CssStyleDeclaration",
|
||||||
"CloseEvent",
|
"CloseEvent",
|
||||||
|
@ -38,6 +39,9 @@ features = [
|
||||||
"DataTransfer",
|
"DataTransfer",
|
||||||
"DragEvent",
|
"DragEvent",
|
||||||
"Element",
|
"Element",
|
||||||
|
"EventListener",
|
||||||
|
"EventListenerOptions",
|
||||||
|
"EventTarget",
|
||||||
"File",
|
"File",
|
||||||
"FileList",
|
"FileList",
|
||||||
"HtmlElement",
|
"HtmlElement",
|
||||||
|
|
|
@ -112,11 +112,13 @@ where
|
||||||
|
|
||||||
let cleanup_fn = {
|
let cleanup_fn = {
|
||||||
let closure_js = closure_js.clone();
|
let closure_js = closure_js.clone();
|
||||||
|
let options = options.clone();
|
||||||
|
|
||||||
move |element: &web_sys::EventTarget| {
|
move |element: &web_sys::EventTarget| {
|
||||||
let _ = element.remove_event_listener_with_callback(
|
let _ = element.remove_event_listener_with_callback_and_event_listener_options(
|
||||||
&event_name,
|
&event_name,
|
||||||
closure_js.as_ref().unchecked_ref(),
|
closure_js.as_ref().unchecked_ref(),
|
||||||
|
options.unchecked_ref(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -125,8 +127,7 @@ where
|
||||||
|
|
||||||
let signal = (target).into();
|
let signal = (target).into();
|
||||||
|
|
||||||
let prev_element: Rc<RefCell<Option<web_sys::EventTarget>>> =
|
let prev_element = Rc::new(RefCell::new(None::<web_sys::EventTarget>));
|
||||||
Rc::new(RefCell::new(signal.get_untracked().map(|e| e.into())));
|
|
||||||
|
|
||||||
let cleanup_prev_element = {
|
let cleanup_prev_element = {
|
||||||
let prev_element = prev_element.clone();
|
let prev_element = prev_element.clone();
|
||||||
|
|
|
@ -24,7 +24,8 @@ use crate::utils::CloneableFnWithArg;
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::{use_websocket, UseWebsocketReturn};
|
/// # use leptos_use::{use_websocket, UseWebsocketReturn};
|
||||||
|
/// # use leptos_use::core::ConnectionReadyState;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # fn Demo() -> impl IntoView {
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
@ -37,16 +38,14 @@ use crate::utils::CloneableFnWithArg;
|
||||||
/// open,
|
/// open,
|
||||||
/// close,
|
/// close,
|
||||||
/// ..
|
/// ..
|
||||||
/// } = use_websocket("wss://echo.websocket.events/".to_string());
|
/// } = use_websocket("wss://echo.websocket.events/");
|
||||||
///
|
///
|
||||||
/// let send_message = move |_| {
|
/// let send_message = move |_| {
|
||||||
/// let m = "Hello, world!".to_string();
|
/// send("Hello, world!".to_string());
|
||||||
/// send(m.clone());
|
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let send_byte_message = move |_| {
|
/// let send_byte_message = move |_| {
|
||||||
/// let m = b"Hello, world!\r\n".to_vec();
|
/// send_bytes(b"Hello, world!\r\n".to_vec());
|
||||||
/// send_bytes(m.clone());
|
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let status = move || ready_state.get().to_string();
|
/// let status = move || ready_state.get().to_string();
|
||||||
|
@ -118,167 +117,167 @@ pub fn use_websocket_with_options(
|
||||||
|
|
||||||
let connect_ref: StoredValue<Option<Rc<dyn Fn()>>> = store_value(None);
|
let connect_ref: StoredValue<Option<Rc<dyn Fn()>>> = store_value(None);
|
||||||
|
|
||||||
// cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
||||||
let on_open_ref = store_value(options.on_open);
|
let on_open_ref = store_value(options.on_open);
|
||||||
let on_message_ref = store_value(options.on_message);
|
let on_message_ref = store_value(options.on_message);
|
||||||
let on_message_bytes_ref = store_value(options.on_message_bytes);
|
let on_message_bytes_ref = store_value(options.on_message_bytes);
|
||||||
let on_error_ref = store_value(options.on_error);
|
let on_error_ref = store_value(options.on_error);
|
||||||
let on_close_ref = store_value(options.on_close);
|
let on_close_ref = store_value(options.on_close);
|
||||||
|
|
||||||
let reconnect_interval = options.reconnect_interval;
|
let reconnect_interval = options.reconnect_interval;
|
||||||
let protocols = options.protocols;
|
let protocols = options.protocols;
|
||||||
|
|
||||||
let reconnect_ref: StoredValue<Option<Rc<dyn Fn()>>> = store_value(None);
|
let reconnect_ref: StoredValue<Option<Rc<dyn Fn()>>> = store_value(None);
|
||||||
reconnect_ref.set_value({
|
reconnect_ref.set_value({
|
||||||
let ws = ws_ref.get_value();
|
let ws = ws_ref.get_value();
|
||||||
Some(Rc::new(move || {
|
Some(Rc::new(move || {
|
||||||
if reconnect_times_ref.get_value() < reconnect_limit
|
if reconnect_times_ref.get_value() < reconnect_limit
|
||||||
&& ws
|
&& ws
|
||||||
.clone()
|
.clone()
|
||||||
.map_or(false, |ws: WebSocket| ws.ready_state() != WebSocket::OPEN)
|
.map_or(false, |ws: WebSocket| ws.ready_state() != WebSocket::OPEN)
|
||||||
{
|
{
|
||||||
reconnect_timer_ref.set_value(
|
reconnect_timer_ref.set_value(
|
||||||
set_timeout_with_handle(
|
set_timeout_with_handle(
|
||||||
move || {
|
move || {
|
||||||
if let Some(connect) = connect_ref.get_value() {
|
if let Some(connect) = connect_ref.get_value() {
|
||||||
connect();
|
connect();
|
||||||
reconnect_times_ref.update_value(|current| *current += 1);
|
reconnect_times_ref.update_value(|current| *current += 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Duration::from_millis(reconnect_interval),
|
Duration::from_millis(reconnect_interval),
|
||||||
)
|
)
|
||||||
.ok(),
|
.ok(),
|
||||||
);
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
|
|
||||||
connect_ref.set_value({
|
|
||||||
let ws = ws_ref.get_value();
|
|
||||||
let url = url;
|
|
||||||
|
|
||||||
Some(Rc::new(move || {
|
|
||||||
reconnect_timer_ref.set_value(None);
|
|
||||||
|
|
||||||
if let Some(web_socket) = &ws {
|
|
||||||
let _ = web_socket.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
let web_socket = {
|
|
||||||
protocols.as_ref().map_or_else(
|
|
||||||
|| WebSocket::new(&url).unwrap_throw(),
|
|
||||||
|protocols| {
|
|
||||||
let array = protocols
|
|
||||||
.iter()
|
|
||||||
.map(|p| JsValue::from(p.clone()))
|
|
||||||
.collect::<Array>();
|
|
||||||
WebSocket::new_with_str_sequence(&url, &JsValue::from(&array))
|
|
||||||
.unwrap_throw()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
};
|
|
||||||
web_socket.set_binary_type(BinaryType::Arraybuffer);
|
|
||||||
set_ready_state.set(ConnectionReadyState::Connecting);
|
|
||||||
|
|
||||||
// onopen handler
|
|
||||||
{
|
|
||||||
let onopen_closure = Closure::wrap(Box::new(move |e: Event| {
|
|
||||||
if unmounted_ref.get_value() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let callback = on_open_ref.get_value();
|
|
||||||
callback(e);
|
|
||||||
|
|
||||||
set_ready_state.set(ConnectionReadyState::Open);
|
|
||||||
}) 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// onmessage handler
|
|
||||||
{
|
|
||||||
let onmessage_closure = Closure::wrap(Box::new(move |e: MessageEvent| {
|
|
||||||
if unmounted_ref.get_value() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.data().dyn_into::<js_sys::ArrayBuffer>().map_or_else(
|
|
||||||
|_| {
|
|
||||||
e.data().dyn_into::<js_sys::JsString>().map_or_else(
|
|
||||||
|_| {
|
|
||||||
unreachable!("message event, received Unknown: {:?}", e.data());
|
|
||||||
},
|
|
||||||
|txt| {
|
|
||||||
let txt = String::from(&txt);
|
|
||||||
let callback = on_message_ref.get_value();
|
|
||||||
callback(txt.clone());
|
|
||||||
|
|
||||||
set_message.set(Some(txt));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|array_buffer| {
|
|
||||||
let array = js_sys::Uint8Array::new(&array_buffer);
|
|
||||||
let array = array.to_vec();
|
|
||||||
let callback = on_message_bytes_ref.get_value();
|
|
||||||
callback(array.clone());
|
|
||||||
|
|
||||||
set_message_bytes.set(Some(array));
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
})
|
}
|
||||||
as Box<dyn FnMut(MessageEvent)>);
|
}))
|
||||||
web_socket.set_onmessage(Some(onmessage_closure.as_ref().unchecked_ref()));
|
});
|
||||||
onmessage_closure.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// onerror handler
|
connect_ref.set_value({
|
||||||
{
|
let ws = ws_ref.get_value();
|
||||||
let onerror_closure = Closure::wrap(Box::new(move |e: Event| {
|
let url = url;
|
||||||
if unmounted_ref.get_value() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(reconnect) = &reconnect_ref.get_value() {
|
Some(Rc::new(move || {
|
||||||
reconnect();
|
reconnect_timer_ref.set_value(None);
|
||||||
}
|
|
||||||
|
|
||||||
let callback = on_error_ref.get_value();
|
if let Some(web_socket) = &ws {
|
||||||
callback(e);
|
let _ = web_socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
set_ready_state.set(ConnectionReadyState::Closed);
|
let web_socket = {
|
||||||
}) as Box<dyn FnMut(Event)>);
|
protocols.as_ref().map_or_else(
|
||||||
web_socket.set_onerror(Some(onerror_closure.as_ref().unchecked_ref()));
|
|| WebSocket::new(&url).unwrap_throw(),
|
||||||
onerror_closure.forget();
|
|protocols| {
|
||||||
}
|
let array = protocols
|
||||||
|
.iter()
|
||||||
|
.map(|p| JsValue::from(p.clone()))
|
||||||
|
.collect::<Array>();
|
||||||
|
WebSocket::new_with_str_sequence(&url, &JsValue::from(&array))
|
||||||
|
.unwrap_throw()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
web_socket.set_binary_type(BinaryType::Arraybuffer);
|
||||||
|
set_ready_state.set(ConnectionReadyState::Connecting);
|
||||||
|
|
||||||
// onclose handler
|
// onopen handler
|
||||||
{
|
{
|
||||||
let onclose_closure = Closure::wrap(Box::new(move |e: CloseEvent| {
|
let onopen_closure = Closure::wrap(Box::new(move |e: Event| {
|
||||||
if unmounted_ref.get_value() {
|
if unmounted_ref.get_value() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(reconnect) = &reconnect_ref.get_value() {
|
let callback = on_open_ref.get_value();
|
||||||
reconnect();
|
callback(e);
|
||||||
}
|
|
||||||
|
|
||||||
let callback = on_close_ref.get_value();
|
set_ready_state.set(ConnectionReadyState::Open);
|
||||||
callback(e);
|
}) 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();
|
||||||
|
}
|
||||||
|
|
||||||
set_ready_state.set(ConnectionReadyState::Closed);
|
// onmessage handler
|
||||||
})
|
{
|
||||||
as Box<dyn FnMut(CloseEvent)>);
|
let onmessage_closure = Closure::wrap(Box::new(move |e: MessageEvent| {
|
||||||
web_socket.set_onclose(Some(onclose_closure.as_ref().unchecked_ref()));
|
if unmounted_ref.get_value() {
|
||||||
onclose_closure.forget();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_ref.set_value(Some(web_socket));
|
e.data().dyn_into::<js_sys::ArrayBuffer>().map_or_else(
|
||||||
}))
|
|_| {
|
||||||
});
|
e.data().dyn_into::<js_sys::JsString>().map_or_else(
|
||||||
// }}
|
|_| {
|
||||||
|
unreachable!("message event, received Unknown: {:?}", e.data());
|
||||||
|
},
|
||||||
|
|txt| {
|
||||||
|
let txt = String::from(&txt);
|
||||||
|
let callback = on_message_ref.get_value();
|
||||||
|
callback(txt.clone());
|
||||||
|
|
||||||
|
set_message.set(Some(txt));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|array_buffer| {
|
||||||
|
let array = js_sys::Uint8Array::new(&array_buffer);
|
||||||
|
let array = array.to_vec();
|
||||||
|
let callback = on_message_bytes_ref.get_value();
|
||||||
|
callback(array.clone());
|
||||||
|
|
||||||
|
set_message_bytes.set(Some(array));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
as Box<dyn FnMut(MessageEvent)>);
|
||||||
|
web_socket.set_onmessage(Some(onmessage_closure.as_ref().unchecked_ref()));
|
||||||
|
onmessage_closure.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// onerror handler
|
||||||
|
{
|
||||||
|
let onerror_closure = Closure::wrap(Box::new(move |e: Event| {
|
||||||
|
if unmounted_ref.get_value() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(reconnect) = &reconnect_ref.get_value() {
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
let callback = on_error_ref.get_value();
|
||||||
|
callback(e);
|
||||||
|
|
||||||
|
set_ready_state.set(ConnectionReadyState::Closed);
|
||||||
|
}) as Box<dyn FnMut(Event)>);
|
||||||
|
web_socket.set_onerror(Some(onerror_closure.as_ref().unchecked_ref()));
|
||||||
|
onerror_closure.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// onclose handler
|
||||||
|
{
|
||||||
|
let onclose_closure = Closure::wrap(Box::new(move |e: CloseEvent| {
|
||||||
|
if unmounted_ref.get_value() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(reconnect) = &reconnect_ref.get_value() {
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
let callback = on_close_ref.get_value();
|
||||||
|
callback(e);
|
||||||
|
|
||||||
|
set_ready_state.set(ConnectionReadyState::Closed);
|
||||||
|
})
|
||||||
|
as Box<dyn FnMut(CloseEvent)>);
|
||||||
|
web_socket.set_onclose(Some(onclose_closure.as_ref().unchecked_ref()));
|
||||||
|
onclose_closure.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
ws_ref.set_value(Some(web_socket));
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
|
||||||
// Send text (String)
|
// Send text (String)
|
||||||
let send = {
|
let send = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue