Fix handling of re-renders in the Router

Previously the router just stored a `root_found` boolean after it picked a
route. But on re-render it would just always return false from `should_render`
if this was true. This just aborted routing after a future resolved (or
anything else that triggered a re-render).

Now we store the matching ScopeId and check that against our routes in a
re-render so we actually do re-render the matching route.
This commit is contained in:
Dave Rolsky committed 2022-01-14 14:55:12 -06:00
1 parent e06eac1ce5
commit 81c094ed29
1 file changed
+13 -8
+13 -8
View File
@@ -11,7 +11,7 @@ pub struct RouterService {
pub(crate) regen_route: Rc<dyn Fn(ScopeId)>, pub(crate) regen_route: Rc<dyn Fn(ScopeId)>,
history: Rc<RefCell<BrowserHistory>>, history: Rc<RefCell<BrowserHistory>>,
slots: Rc<RefCell<Vec<(ScopeId, String)>>>, slots: Rc<RefCell<Vec<(ScopeId, String)>>>,
root_found: Rc<Cell<bool>>, root_found: Rc<Cell<Option<ScopeId>>>,
cur_path_params: Rc<RefCell<HashMap<String, String>>>, cur_path_params: Rc<RefCell<HashMap<String, String>>>,
listener: HistoryListener, listener: HistoryListener,
} }
@@ -39,11 +39,11 @@ impl RouterService {
let _slots = slots.clone(); let _slots = slots.clone();
let root_found = Rc::new(Cell::new(false)); let root_found = Rc::new(Cell::new(None));
let regen = regen_route.clone(); let regen = regen_route.clone();
let _root_found = root_found.clone(); let _root_found = root_found.clone();
let listener = history.listen(move || { let listener = history.listen(move || {
_root_found.set(false); _root_found.set(None);
// checking if the route is valid is cheap, so we do it // checking if the route is valid is cheap, so we do it
for (slot, root) in _slots.borrow_mut().iter().rev() { for (slot, root) in _slots.borrow_mut().iter().rev() {
log::trace!("regenerating slot {:?} for root '{}'", slot, root); log::trace!("regenerating slot {:?} for root '{}'", slot, root);
@@ -74,8 +74,13 @@ impl RouterService {
pub fn should_render(&self, scope: ScopeId) -> bool { pub fn should_render(&self, scope: ScopeId) -> bool {
log::trace!("Should render scope id {:?}?", scope); log::trace!("Should render scope id {:?}?", scope);
if self.root_found.get() { if let Some(root_id) = self.root_found.get() {
log::trace!(" no - because root_found is true"); log::trace!(" we already found a root with scope id {:?}", root_id);
if root_id == scope {
log::trace!(" yes - it's a match");
return true;
}
log::trace!(" no - it's not a match");
return false; return false;
} }
@@ -89,7 +94,7 @@ impl RouterService {
// fallback logic // fallback logic
match root { match root {
Some((_id, route)) => { Some((id, route)) => {
log::trace!( log::trace!(
" matched given scope id {:?} with route root '{}'", " matched given scope id {:?} with route root '{}'",
scope, scope,
@@ -97,13 +102,13 @@ impl RouterService {
); );
if let Some(params) = route_matches_path(route, path) { if let Some(params) = route_matches_path(route, path) {
log::trace!(" and it matches the current path '{}'", path); log::trace!(" and it matches the current path '{}'", path);
self.root_found.set(true); self.root_found.set(Some(*id));
*self.cur_path_params.borrow_mut() = params; *self.cur_path_params.borrow_mut() = params;
true true
} else { } else {
if route == "" { if route == "" {
log::trace!(" and the route is the root, so we will use that without a better match"); log::trace!(" and the route is the root, so we will use that without a better match");
self.root_found.set(true); self.root_found.set(Some(*id));
true true
} else { } else {
log::trace!(" and the route '{}' is not the root nor does it match the current path", route); log::trace!(" and the route '{}' is not the root nor does it match the current path", route);