yew_hooks/hooks/
use_location.rs

1use gloo::utils::window;
2use wasm_bindgen::JsValue;
3use yew::prelude::*;
4
5use super::use_event_with_window;
6
7/// State for brower's location.
8pub struct LocationState {
9    pub trigger: String,
10    pub state: Option<JsValue>,
11    pub length: u32,
12    pub hash: String,
13    pub host: String,
14    pub hostname: String,
15    pub href: String,
16    pub origin: String,
17    pub pathname: String,
18    pub port: String,
19    pub protocol: String,
20    pub search: String,
21}
22
23/// A sensor hook that tracks brower's location value.
24///
25/// # Example
26///
27/// ```rust
28/// # use yew::prelude::*;
29/// #
30/// use yew_hooks::prelude::*;
31///
32/// #[function_component(UseLocation)]
33/// fn location() -> Html {
34///     let location = use_location();
35///    
36///     html! {
37///         <>
38///             <p>
39///                 <b>{ "trigger: " }</b>
40///                 { &location.trigger }
41///             </p>
42///             <p>
43///                 <b>{ "state: " }</b>
44///                 { format!("{:?}", &location.state) }
45///             </p>
46///             <p>
47///                 <b>{ "length: " }</b>
48///                 { &location.length }
49///             </p>
50///             <p>
51///                 <b>{ "hash: " }</b>
52///                 { &location.hash }
53///             </p>
54///             <p>
55///                 <b>{ "host: " }</b>
56///                 { &location.host }
57///             </p>
58///             <p>
59///                 <b>{ "hostname: " }</b>
60///                 { &location.hostname }
61///             </p>
62///             <p>
63///                 <b>{ "href: " }</b>
64///                 { &location.href }
65///             </p>
66///             <p>
67///                 <b>{ "origin: " }</b>
68///                 { &location.origin }
69///             </p>
70///             <p>
71///                 <b>{ "pathname: " }</b>
72///                 { &location.pathname }
73///             </p>
74///             <p>
75///                 <b>{ "port: " }</b>
76///                 { &location.port }
77///             </p>
78///             <p>
79///                 <b>{ "protocol: " }</b>
80///                 { &location.protocol }
81///             </p>
82///             <p>
83///                 <b>{ "search: " }</b>
84///                 { &location.search }
85///             </p>
86///         </>
87///     }
88/// }
89/// ```
90#[hook]
91pub fn use_location() -> UseStateHandle<LocationState> {
92    let state = use_state(|| build_location("load".to_string()));
93
94    {
95        let state = state.clone();
96        use_event_with_window("popstate", move |_: Event| {
97            state.set(build_location("popstate".to_string()));
98        });
99    }
100
101    {
102        let state = state.clone();
103        use_event_with_window("pushstate", move |_: Event| {
104            state.set(build_location("pushstate".to_string()));
105        });
106    }
107
108    {
109        let state = state.clone();
110        use_event_with_window("replacestate", move |_: Event| {
111            state.set(build_location("replacestate".to_string()));
112        });
113    }
114
115    state
116}
117
118fn build_location(trigger: String) -> LocationState {
119    let location = window().location();
120    let history = window().history().map_or((None, 0), |history| {
121        (
122            history.state().ok(),
123            history.length().map_or(0, |length| length),
124        )
125    });
126
127    LocationState {
128        trigger,
129        state: history.0,
130        length: history.1,
131        hash: location.hash().unwrap_or_default(),
132        host: location.host().unwrap_or_default(),
133        hostname: location.hostname().unwrap_or_default(),
134        href: location.href().unwrap_or_default(),
135        origin: location.origin().unwrap_or_default(),
136        pathname: location.pathname().unwrap_or_default(),
137        port: location.port().unwrap_or_default(),
138        protocol: location.protocol().unwrap_or_default(),
139        search: location.search().unwrap_or_default(),
140    }
141}