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(|| {
|
||||
provide_router_context(RouterContext::new(props.config.call(())));
|
||||
|
||||
provide_context(OutletContext::<R> {
|
||||
current_level: 0,
|
||||
_marker: std::marker::PhantomData,
|
||||
});
|
||||
|
||||
use_hook(|| {
|
||||
provide_context(OutletContext::<R>::new());
|
||||
});
|
||||
|
||||
rsx! { Outlet::<R> {} }
|
||||
|
||||
@@ -2,43 +2,50 @@ use dioxus_lib::prelude::*;
|
||||
|
||||
use crate::{routable::Routable, utils::use_router_internal::use_router_internal};
|
||||
|
||||
pub(crate) struct OutletContext<R> {
|
||||
pub current_level: usize,
|
||||
pub _marker: std::marker::PhantomData<R>,
|
||||
}
|
||||
|
||||
impl<R> Clone for OutletContext<R> {
|
||||
fn clone(&self) -> Self {
|
||||
OutletContext {
|
||||
current_level: self.current_level,
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
})
|
||||
/// A context that manages nested routing levels for outlet components.
|
||||
///
|
||||
/// The outlet context keeps track of the current nesting level of routes and helps
|
||||
/// manage the hierarchical structure of nested routes in the application.
|
||||
///
|
||||
/// # Type Parameters
|
||||
///
|
||||
/// * `R` - The routable type that implements the routing logic
|
||||
#[derive(Clone, Default)]
|
||||
pub struct OutletContext<R> {
|
||||
current_level: usize,
|
||||
_marker: std::marker::PhantomData<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
|
||||
where
|
||||
R: Routable + Clone,
|
||||
{
|
||||
let router = use_router_internal().expect("Outlet must be inside of a router");
|
||||
let outlet: OutletContext<R> = use_outlet_context();
|
||||
let current_level = outlet.current_level;
|
||||
provide_context({
|
||||
OutletContext::<R> {
|
||||
current_level: current_level + 1,
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
});
|
||||
let current_level = outlet.level();
|
||||
provide_context(outlet.next());
|
||||
|
||||
if let Some(error) = router.render_error() {
|
||||
return if current_level == 0 {
|
||||
@@ -51,3 +58,26 @@ impl<R> OutletContext<R> {
|
||||
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 {
|
||||
pub(crate) mod navigator;
|
||||
pub(crate) mod outlet;
|
||||
pub use outlet::{use_outlet_context, OutletContext};
|
||||
pub(crate) mod router;
|
||||
pub use navigator::*;
|
||||
pub(crate) use router::*;
|
||||
|
||||
Reference in new issue
Block a user