mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
Fix context in outlets (#374)
* Add `Scope::parent()` to make access to parent `Scope` possible. * Handle context properly in nested routes
This commit is contained in:
parent
154e42f3f4
commit
fc7199f188
4 changed files with 27 additions and 13 deletions
|
@ -234,6 +234,19 @@ impl Scope {
|
|||
f(&mut scope.borrow_mut());
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the the parent Scope, if any.
|
||||
pub fn parent(&self) -> Option<Scope> {
|
||||
with_runtime(self.runtime, |runtime| {
|
||||
runtime.scope_parents.borrow().get(self.id).copied()
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|id| Scope {
|
||||
runtime: self.runtime,
|
||||
id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a cleanup function, which will be run when a [Scope] is disposed.
|
||||
|
|
|
@ -11,7 +11,7 @@ pub fn Outlet(cx: Scope) -> impl IntoView {
|
|||
let is_showing = Rc::new(Cell::new(None::<(usize, Scope)>));
|
||||
let (outlet, set_outlet) = create_signal(cx, None::<View>);
|
||||
create_isomorphic_effect(cx, move |_| {
|
||||
match (route.child(), &is_showing.get()) {
|
||||
match (route.child(cx), &is_showing.get()) {
|
||||
(None, prev) => {
|
||||
if let Some(prev_scope) = prev.map(|(_, scope)| scope) {
|
||||
prev_scope.dispose();
|
||||
|
|
|
@ -79,7 +79,7 @@ impl RouteContext {
|
|||
pub(crate) fn new(
|
||||
cx: Scope,
|
||||
router: &RouterContext,
|
||||
child: impl Fn() -> Option<RouteContext> + 'static,
|
||||
child: impl Fn(Scope) -> Option<RouteContext> + 'static,
|
||||
matcher: impl Fn() -> Option<RouteMatch> + 'static,
|
||||
) -> Option<Self> {
|
||||
let base = router.base();
|
||||
|
@ -151,7 +151,7 @@ impl RouteContext {
|
|||
cx,
|
||||
id: 0,
|
||||
base_path: path.to_string(),
|
||||
child: Box::new(|| None),
|
||||
child: Box::new(|_| None),
|
||||
path: RefCell::new(path.to_string()),
|
||||
original_path: path.to_string(),
|
||||
params: create_memo(cx, |_| ParamsMap::new()),
|
||||
|
@ -166,8 +166,8 @@ impl RouteContext {
|
|||
}
|
||||
|
||||
/// The nested child route, if any.
|
||||
pub fn child(&self) -> Option<RouteContext> {
|
||||
(self.inner.child)()
|
||||
pub fn child(&self, cx: Scope) -> Option<RouteContext> {
|
||||
(self.inner.child)(cx)
|
||||
}
|
||||
|
||||
/// The view associated with the current route.
|
||||
|
@ -180,7 +180,7 @@ pub(crate) struct RouteContextInner {
|
|||
cx: Scope,
|
||||
base_path: String,
|
||||
pub(crate) id: usize,
|
||||
pub(crate) child: Box<dyn Fn() -> Option<RouteContext>>,
|
||||
pub(crate) child: Box<dyn Fn(Scope) -> Option<RouteContext>>,
|
||||
pub(crate) path: RefCell<String>,
|
||||
pub(crate) original_path: String,
|
||||
pub(crate) params: Memo<ParamsMap>,
|
||||
|
@ -202,7 +202,6 @@ impl std::fmt::Debug for RouteContextInner {
|
|||
f.debug_struct("RouteContextInner")
|
||||
.field("path", &self.path)
|
||||
.field("ParamsMap", &self.params)
|
||||
.field("child", &(self.child)())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,8 @@ pub fn Routes(
|
|||
#[prop(optional)] base: Option<String>,
|
||||
children: Box<dyn FnOnce(Scope) -> Fragment>,
|
||||
) -> impl IntoView {
|
||||
let router = use_context::<RouterContext>(cx).unwrap_or_else(|| {
|
||||
log::warn!("<Routes/> component should be nested within a <Router/>.");
|
||||
panic!()
|
||||
});
|
||||
let router = use_context::<RouterContext>(cx)
|
||||
.expect("<Routes/> component should be nested within a <Router/>.");
|
||||
let base_route = router.base();
|
||||
|
||||
let mut branches = Vec::new();
|
||||
|
@ -86,6 +84,8 @@ pub fn Routes(
|
|||
.map(|prev_matches| next_matches.len() == prev_matches.len())
|
||||
.unwrap_or(false);
|
||||
|
||||
let prev_cx = Rc::new(Cell::new(cx));
|
||||
|
||||
for i in 0..next_matches.len() {
|
||||
let next = next.clone();
|
||||
let prev_match = prev_matches.and_then(|p| p.get(i));
|
||||
|
@ -112,17 +112,19 @@ pub fn Routes(
|
|||
root_equal.set(false);
|
||||
}
|
||||
|
||||
let disposer = cx.child_scope({
|
||||
let disposer = prev_cx.get().child_scope({
|
||||
let next = next.clone();
|
||||
let router = Rc::clone(&router.inner);
|
||||
let prev_cx = Rc::clone(&prev_cx);
|
||||
move |cx| {
|
||||
prev_cx.set(cx);
|
||||
let next = next.clone();
|
||||
let next_ctx = RouteContext::new(
|
||||
cx,
|
||||
&RouterContext { inner: router },
|
||||
{
|
||||
let next = next.clone();
|
||||
move || {
|
||||
move |cx| {
|
||||
if let Some(route_states) =
|
||||
use_context::<Memo<RouterState>>(cx)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue