yew_hooks/hooks/
use_hash.rs

1use std::ops::Deref;
2
3use gloo::utils::window;
4use yew::prelude::*;
5
6use super::use_event_with_window;
7
8/// State handle for the [`use_hash`] hook.
9pub struct UseHashHandle {
10    inner: UseStateHandle<String>,
11}
12
13impl UseHashHandle {
14    pub fn set(&self, hash: String) {
15        if *self.inner != hash {
16            let _ = window().location().set_hash(hash.as_str());
17        }
18    }
19}
20
21impl Deref for UseHashHandle {
22    type Target = String;
23
24    fn deref(&self) -> &Self::Target {
25        &self.inner
26    }
27}
28
29impl Clone for UseHashHandle {
30    fn clone(&self) -> Self {
31        Self {
32            inner: self.inner.clone(),
33        }
34    }
35}
36
37impl PartialEq for UseHashHandle {
38    fn eq(&self, other: &Self) -> bool {
39        *self.inner == *other.inner
40    }
41}
42
43/// A sensor hook that tracks brower's location hash value.
44///
45/// # Example
46///
47/// ```rust
48/// # use yew::prelude::*;
49/// #
50/// use yew_hooks::prelude::*;
51///
52/// #[function_component(UseHash)]
53/// fn hash() -> Html {
54///     let hash = use_hash();
55///
56///     let onclick = {
57///         let hash = hash.clone();
58///         Callback::from(move |_| {
59///             hash.set("#/path/to/page?userId=123".to_string())
60///         })
61///     };
62///    
63///     html! {
64///         <>
65///             <button {onclick}>{ "Set hash to #/path/to/page?userId=123" }</button>
66///             <p>
67///                 <b>{ " Current hash: " }</b>
68///                 { &*hash }
69///             </p>
70///         </>
71///     }
72/// }
73/// ```
74#[hook]
75pub fn use_hash() -> UseHashHandle {
76    let inner = use_state(|| window().location().hash().unwrap_or_default());
77
78    {
79        let inner = inner.clone();
80        use_event_with_window("hashchange", move |_: Event| {
81            inner.set(window().location().hash().unwrap_or_default());
82        });
83    }
84
85    UseHashHandle { inner }
86}