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}