yew-hooks 0.6.3

Hooks for the Yew web framework, inspired by react hook libs like streamich/react-use and alibaba/hooks.
Documentation
use wasm_bindgen::{prelude::*, JsCast};
use web_sys::Element;
use yew::prelude::*;

use super::use_raf_state;
use crate::web_sys_ext::{ResizeObserver, ResizeObserverEntry};

/// A sensor hook that tracks an HTML element's dimensions using the `ResizeObserver` API.
///
/// # Example
///
/// ```rust
/// # use yew::prelude::*;
/// #
/// use yew_hooks::prelude::*;
///
/// #[function_component(UseSize)]
/// fn size() -> Html {
///     let node =  use_node_ref();
///     let state = use_size(node.clone());
///     
///     html! {
///         <div ref={node}>
///             <b>{ " Width: " }</b>
///             { state.0 }
///             <b>{ " Height: " }</b>
///             { state.1 }
///         </div>
///     }
/// }
/// ```
#[hook]
pub fn use_size(node: NodeRef) -> (u32, u32) {
    let state = use_raf_state(|| (0, 0));

    {
        let state = state.clone();
        use_effect_with(node, move |node| {
            let closure = Closure::wrap(Box::new(move |entries: Vec<ResizeObserverEntry>| {
                for entry in &entries {
                    let element = entry.target();
                    state.set((
                        element.client_width() as u32,
                        element.client_height() as u32,
                    ));
                }
            }) as Box<dyn Fn(Vec<ResizeObserverEntry>)>);

            let observer = ResizeObserver::new(closure.as_ref().unchecked_ref()).unwrap_throw();
            // Forget the closure to keep it alive
            closure.forget();

            if let Some(element) = &node.cast::<Element>() {
                observer.observe(element);
            }

            move || observer.disconnect()
        });
    }

    *state
}