Expose Outlet Context (#3788)
* Expose Outlet Context * feat(router): expose OutletContext and use_outlet_context for improved accessibility * Hide OutletContext properties * Starts from 0 ? * Clippy fix with Default
This commit is contained in:
1 parent
f4c59e1188
commit
6a0ae17d56
3 files changed
+62
-32
No files matched your search
@@ -47,11 +47,10 @@ where
|
|||||||
|
|
||||||
use_hook(|| {
|
use_hook(|| {
|
||||||
provide_router_context(RouterContext::new(props.config.call(())));
|
provide_router_context(RouterContext::new(props.config.call(())));
|
||||||
|
});
|
||||||
|
|
||||||
provide_context(OutletContext::<R> {
|
use_hook(|| {
|
||||||
current_level: 0,
|
provide_context(OutletContext::<R>::new());
|
||||||
_marker: std::marker::PhantomData,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
rsx! { Outlet::<R> {} }
|
rsx! { Outlet::<R> {} }
|
||||||
|
|||||||
@@ -2,43 +2,50 @@ use dioxus_lib::prelude::*;
|
|||||||
|
|
||||||
use crate::{routable::Routable, utils::use_router_internal::use_router_internal};
|
use crate::{routable::Routable, utils::use_router_internal::use_router_internal};
|
||||||
|
|
||||||
pub(crate) struct OutletContext<R> {
|
/// A context that manages nested routing levels for outlet components.
|
||||||
pub current_level: usize,
|
///
|
||||||
pub _marker: std::marker::PhantomData<R>,
|
/// The outlet context keeps track of the current nesting level of routes and helps
|
||||||
}
|
/// manage the hierarchical structure of nested routes in the application.
|
||||||
|
///
|
||||||
impl<R> Clone for OutletContext<R> {
|
/// # Type Parameters
|
||||||
fn clone(&self) -> Self {
|
///
|
||||||
OutletContext {
|
/// * `R` - The routable type that implements the routing logic
|
||||||
current_level: self.current_level,
|
#[derive(Clone, Default)]
|
||||||
_marker: std::marker::PhantomData,
|
pub struct OutletContext<R> {
|
||||||
}
|
current_level: usize,
|
||||||
}
|
_marker: std::marker::PhantomData<R>,
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn use_outlet_context<R: 'static>() -> OutletContext<R> {
|
|
||||||
use_hook(|| {
|
|
||||||
try_consume_context().unwrap_or(OutletContext::<R> {
|
|
||||||
current_level: 1,
|
|
||||||
_marker: std::marker::PhantomData,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> OutletContext<R> {
|
impl<R> OutletContext<R> {
|
||||||
|
/// Creates a new outlet context starting at level 1
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
current_level: 0,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new outlet context for the next nesting level
|
||||||
|
pub fn next(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
current_level: self.current_level + 1,
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the current nesting level of this outlet
|
||||||
|
pub fn level(&self) -> usize {
|
||||||
|
self.current_level
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn render() -> Element
|
pub(crate) fn render() -> Element
|
||||||
where
|
where
|
||||||
R: Routable + Clone,
|
R: Routable + Clone,
|
||||||
{
|
{
|
||||||
let router = use_router_internal().expect("Outlet must be inside of a router");
|
let router = use_router_internal().expect("Outlet must be inside of a router");
|
||||||
let outlet: OutletContext<R> = use_outlet_context();
|
let outlet: OutletContext<R> = use_outlet_context();
|
||||||
let current_level = outlet.current_level;
|
let current_level = outlet.level();
|
||||||
provide_context({
|
provide_context(outlet.next());
|
||||||
OutletContext::<R> {
|
|
||||||
current_level: current_level + 1,
|
|
||||||
_marker: std::marker::PhantomData,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(error) = router.render_error() {
|
if let Some(error) = router.render_error() {
|
||||||
return if current_level == 0 {
|
return if current_level == 0 {
|
||||||
@@ -51,3 +58,26 @@ impl<R> OutletContext<R> {
|
|||||||
router.current::<R>().render(current_level)
|
router.current::<R>().render(current_level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the current outlet context from the component hierarchy.
|
||||||
|
///
|
||||||
|
/// This hook retrieves the outlet context from the current component scope. If no context is found,
|
||||||
|
/// it creates a new context with a default level of 1.
|
||||||
|
///
|
||||||
|
/// # Type Parameters
|
||||||
|
///
|
||||||
|
/// * `R` - The routable type that implements the routing logic
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns an [`OutletContext<R>`] containing the current nesting level information.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// let outlet_ctx = use_outlet_context::<MyRouter>();
|
||||||
|
/// println!("Current nesting level: {}", outlet_ctx.level());
|
||||||
|
/// ```
|
||||||
|
pub fn use_outlet_context<R: Clone + 'static>() -> OutletContext<R> {
|
||||||
|
use_hook(|| try_consume_context().unwrap_or_else(OutletContext::new))
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ pub mod components {
|
|||||||
mod contexts {
|
mod contexts {
|
||||||
pub(crate) mod navigator;
|
pub(crate) mod navigator;
|
||||||
pub(crate) mod outlet;
|
pub(crate) mod outlet;
|
||||||
|
pub use outlet::{use_outlet_context, OutletContext};
|
||||||
pub(crate) mod router;
|
pub(crate) mod router;
|
||||||
pub use navigator::*;
|
pub use navigator::*;
|
||||||
pub(crate) use router::*;
|
pub(crate) use router::*;
|
||||||
|
|||||||
Reference in new issue
Block a user