fix: relative routing should update when navigating between <Outlet/>s (closes issue #725) (#729)

* clear some cruft out of the navigation code
* fix issue #725 (correctly reactively resolving paths)
This commit is contained in:
Greg Johnston 2023-03-22 19:59:08 -04:00 committed by GitHub
parent 509223ab2e
commit 286f3eebe4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 56 deletions

View file

@ -3,10 +3,7 @@ use crate::{
ParamsMap, RouterContext, SsrMode,
};
use leptos::{leptos_dom::Transparent, *};
use std::{
cell::{Cell, RefCell},
rc::Rc,
};
use std::{cell::Cell, rc::Rc};
thread_local! {
static ROUTE_ID: Cell<usize> = Cell::new(0);
@ -121,7 +118,7 @@ impl RouteContext {
id,
base_path: base,
child: Box::new(child),
path: RefCell::new(path),
path: create_rw_signal(cx, path),
original_path: route.original_path.to_string(),
params,
outlet: Box::new(move |cx| Some(element(cx))),
@ -144,11 +141,11 @@ impl RouteContext {
/// e.g., this will return `/article/0` rather than `/article/:id`.
/// For the opposite behavior, see [RouteContext::original_path].
pub fn path(&self) -> String {
self.inner.path.borrow().to_string()
self.inner.path.get_untracked()
}
pub(crate) fn set_path(&mut self, path: String) {
*self.inner.path.borrow_mut() = path;
pub(crate) fn set_path(&self, path: String) {
self.inner.path.set(path);
}
/// Returns the original URL path of the current route,
@ -176,7 +173,7 @@ impl RouteContext {
id: 0,
base_path: path.to_string(),
child: Box::new(|_| None),
path: RefCell::new(path.to_string()),
path: create_rw_signal(cx, path.to_string()),
original_path: path.to_string(),
params: create_memo(cx, |_| ParamsMap::new()),
outlet: Box::new(move |cx| {
@ -188,7 +185,16 @@ impl RouteContext {
/// Resolves a relative route, relative to the current route's path.
pub fn resolve_path(&self, to: &str) -> Option<String> {
resolve_path(&self.inner.base_path, to, Some(&self.inner.path.borrow()))
resolve_path(
&self.inner.base_path,
to,
Some(&self.inner.path.get_untracked()),
)
.map(String::from)
}
pub(crate) fn resolve_path_tracked(&self, to: &str) -> Option<String> {
resolve_path(&self.inner.base_path, to, Some(&self.inner.path.get()))
.map(String::from)
}
@ -208,7 +214,7 @@ pub(crate) struct RouteContextInner {
base_path: String,
pub(crate) id: usize,
pub(crate) child: Box<dyn Fn(Scope) -> Option<RouteContext>>,
pub(crate) path: RefCell<String>,
pub(crate) path: RwSignal<String>,
pub(crate) original_path: String,
pub(crate) params: Memo<ParamsMap>,
pub(crate) outlet: Box<dyn Fn(Scope) -> Option<View>>,

View file

@ -221,55 +221,36 @@ impl RouterContextInner {
if resolved_to != this.reference.get()
|| options.state != (this.state).get()
{
if cfg!(feature = "server") {
self.history.navigate(&LocationChange {
value: resolved_to,
{
self.referrers.borrow_mut().push(LocationChange {
value: self.reference.get(),
replace: options.replace,
scroll: options.scroll,
state: options.state.clone(),
state: self.state.get(),
});
} else {
{
self.referrers.borrow_mut().push(
LocationChange {
value: self.reference.get(),
replace: options.replace,
scroll: options.scroll,
state: self.state.get(),
},
);
}
let len = self.referrers.borrow().len();
}
let len = self.referrers.borrow().len();
#[cfg(feature = "transition")]
let transition = use_transition(self.cx);
//transition.start({
let set_reference = self.set_reference;
let set_state = self.set_state;
let referrers = self.referrers.clone();
let this = Rc::clone(&self);
//move || {
let set_reference = self.set_reference;
let set_state = self.set_state;
let referrers = self.referrers.clone();
let this = Rc::clone(&self);
let resolved = resolved_to.to_string();
let state = options.state.clone();
queue_microtask(move || {
set_reference.update(move |r| *r = resolved);
let resolved = resolved_to.to_string();
let state = options.state.clone();
set_reference.update(move |r| *r = resolved);
set_state.update({
let next_state = state.clone();
move |state| *state = next_state
});
if referrers.borrow().len() == len {
this.navigate_end(LocationChange {
value: resolved_to.to_string(),
replace: false,
scroll: true,
state,
})
//}
}
});
//});
set_state.update({
let next_state = state.clone();
move |state| *state = next_state
});
if referrers.borrow().len() == len {
this.navigate_end(LocationChange {
value: resolved_to,
replace: false,
scroll: true,
state,
})
}
}

View file

@ -88,7 +88,7 @@ pub fn Routes(
if next_match.route.key == prev_match.route.key
&& next_match.route.id == prev_match.route.id =>
{
let mut prev_one = { prev.borrow()[i].clone() };
let prev_one = { prev.borrow()[i].clone() };
if next_match.path_match.path != prev_one.path() {
prev_one
.set_path(next_match.path_match.path.clone());

View file

@ -70,7 +70,7 @@ pub fn use_resolved_path(
if path.starts_with('/') {
Some(path)
} else {
route.resolve_path(&path).map(String::from)
route.resolve_path_tracked(&path).map(String::from)
}
})
}