diff --git a/packages/router/src/hooks/use_route.rs b/packages/router/src/hooks/use_route.rs index 97dd6c048..ab6fad268 100644 --- a/packages/router/src/hooks/use_route.rs +++ b/packages/router/src/hooks/use_route.rs @@ -1,4 +1,4 @@ -use dioxus_core::ScopeState; +use dioxus_core::{ScopeId, ScopeState}; use gloo::history::{HistoryResult, Location}; use serde::de::DeserializeOwned; use std::{rc::Rc, str::FromStr}; @@ -74,10 +74,28 @@ impl UseRoute { /// This hook provides access to information about the current location in the /// context of a [`Router`]. If this function is called outside of a `Router` /// component it will panic. -pub fn use_route(cx: &ScopeState) -> UseRoute { - let router = cx - .consume_context::() - .expect("Cannot call use_route outside the scope of a Router component") - .clone(); - UseRoute { router } +pub fn use_route(cx: &ScopeState) -> &UseRoute { + &cx.use_hook(|_| { + let router = cx + .consume_context::() + .expect("Cannot call use_route outside the scope of a Router component"); + + router.subscribe_onchange(cx.scope_id()); + + UseRouteInner { + router: UseRoute { router }, + scope: cx.scope_id(), + } + }) + .router +} + +struct UseRouteInner { + router: UseRoute, + scope: ScopeId, +} +impl Drop for UseRouteInner { + fn drop(&mut self) { + self.router.router.unsubscribe_onchange(self.scope) + } } diff --git a/packages/router/src/service.rs b/packages/router/src/service.rs index 9da2bef7e..f2682f1f0 100644 --- a/packages/router/src/service.rs +++ b/packages/router/src/service.rs @@ -1,7 +1,7 @@ use gloo::history::{BrowserHistory, History, HistoryListener, Location}; use std::{ cell::{Cell, Ref, RefCell}, - collections::HashMap, + collections::{HashMap, HashSet}, rc::Rc, }; @@ -12,6 +12,7 @@ pub struct RouterService { pub(crate) pending_events: Rc>>, history: Rc>, slots: Rc>>, + onchange_listeners: Rc>>, root_found: Rc>>, cur_path_params: Rc>>, listener: HistoryListener, @@ -73,6 +74,7 @@ impl RouterService { regen_route, slots, pending_events, + onchange_listeners: Rc::new(RefCell::new(HashSet::new())), cur_path_params: Rc::new(RefCell::new(HashMap::new())), } } @@ -143,6 +145,16 @@ impl RouterService { pub fn current_path_params(&self) -> Ref> { self.cur_path_params.borrow() } + + pub fn subscribe_onchange(&self, id: ScopeId) { + log::trace!("Subscribing onchange for scope id {:?}", id); + self.onchange_listeners.borrow_mut().insert(id); + } + + pub fn unsubscribe_onchange(&self, id: ScopeId) { + log::trace!("Subscribing onchange for scope id {:?}", id); + self.onchange_listeners.borrow_mut().remove(&id); + } } fn clean_route(route: String) -> String {