pub struct ClientRouter { /* private fields */ }client-router only.Expand description
The main client-side router.
ClientRouter renders views using the Page type.
§Clone semantics
The Clone impl is shallow by design. Signal fields share their
underlying reactive state across clones, and on WASM the navigation
observer state (held behind Rc) is shared as well; only the route
table (Vec<ClientRoute> / HashMap<String, usize>) is copied
independently. As a result two clones see the same navigation state
but can diverge if either is mutated to register new routes — this
is not a deep clone of the router.
In practice Clone is only invoked by
collect_client_router_from_inventory (Refs #4453) as the fallback
path for Arc::try_unwrap when the underlying factory Arc is
shared, and ClientLauncher::register_routes_from_inventory() is the
only caller. Application code should NOT call .clone() directly to
“branch” routers; treat the router as a single owned value moved
into the launcher. Refs Copilot review on PR #4477.
Implementations§
Source§impl ClientRouter
impl ClientRouter
Sourcepub fn new() -> ClientRouter
Available on crate feature pages only.
pub fn new() -> ClientRouter
pages only.Creates a new router.
Sourcepub fn merge(self, other: ClientRouter) -> ClientRouter
Available on crate feature pages only.
pub fn merge(self, other: ClientRouter) -> ClientRouter
pages only.Combine another ClientRouter into this one.
Routes and named-route mappings from other are appended to self,
preserving the order in which routes were originally registered. The
reactive signals (current_path, current_params, current_route_name)
and the not_found handler from other are discarded — self’s
observation state is the one that drives the merged router.
§Named-route collisions
If both routers register the same named route, the entry from other
overwrites the entry from self (last-wins). This matches the way
UnifiedRouter::mount_unified already composes per-app routers, and
keeps merge callable in chains where the caller does not want to
handle errors. Use ClientRouter::try_merge for a fallible variant
that surfaces collisions instead of silently shadowing them.
§Examples
Composing per-app SPA routers into the single
ClientRouter that ClientLauncher::router_client expects:
let router = polls_client_url_patterns()
.merge(users_client_url_patterns());Sourcepub fn try_merge(self, other: ClientRouter) -> Result<ClientRouter, MergeError>
Available on crate feature pages only.
pub fn try_merge(self, other: ClientRouter) -> Result<ClientRouter, MergeError>
pages only.Like ClientRouter::merge, but fail if any named route collides.
Validates first, so on Err self is dropped without being mutated.
On success the semantics are identical to merge (routes appended,
other’s signals and not_found discarded).
§Errors
Returns MergeError::NameCollision carrying a colliding name when
at least one named route is registered in both routers. When several
names collide, the returned name is one of them; the choice is
unspecified because named routes are stored in a HashMap.
§Examples
match polls_client_url_patterns().try_merge(users_client_url_patterns()) {
Ok(router) => launcher.router_client(|| router),
Err(MergeError::NameCollision { name }) => {
panic!("two apps register the route `{name}`");
}
}Sourcepub fn with_namespace(self, namespace: &str) -> ClientRouter
Available on crate feature pages only.
pub fn with_namespace(self, namespace: &str) -> ClientRouter
pages only.Prefix all named route keys with "namespace:".
This is the client-side equivalent of ServerRouter::with_namespace().
Called by client/unified route declarations to ensure registered
names match the "app:route" format used by per-app resolver
structs.
Sourcepub fn with_route_metadata(
self,
name: &str,
metadata: RouteMetadata,
) -> ClientRouter
Available on crate feature pages only.
pub fn with_route_metadata( self, name: &str, metadata: RouteMetadata, ) -> ClientRouter
pages only.Sourcepub fn route<F>(self, name: &str, pattern: &str, component: F) -> ClientRouter
Available on crate feature pages only.
pub fn route<F>(self, name: &str, pattern: &str, component: F) -> ClientRouter
pages only.Adds a named route to the router.
Every route requires a unique name for reverse URL lookup.
§Panics
Panics if name duplicates an already-registered route name.
Sourcepub fn route_params<F, T>(
self,
name: &str,
pattern: &str,
handler: F,
) -> ClientRouter
Available on crate feature pages only.
pub fn route_params<F, T>( self, name: &str, pattern: &str, handler: F, ) -> ClientRouter
pages only.Adds a named route with typed path parameters.
§Panics
Panics if name duplicates an already-registered route name.
Sourcepub fn route_result<F, T, E>(
self,
name: &str,
pattern: &str,
handler: F,
) -> ClientRouter
Available on crate feature pages only.
pub fn route_result<F, T, E>( self, name: &str, pattern: &str, handler: F, ) -> ClientRouter
pages only.Adds a named route with typed path parameters that returns a Result.
§Panics
Panics if name duplicates an already-registered route name.
Sourcepub fn page<F, P>(self, name: &str, pattern: &str, handler: F) -> ClientRouter
Available on crate feature pages only.
pub fn page<F, P>(self, name: &str, pattern: &str, handler: F) -> ClientRouter
pages only.Adds a named route whose handler receives a single Props struct
constructed via FromRequest (Manouche DSL v2 spec §4.3).
This is the canonical v2 route-handler shape: the same Props
struct can be used both as a Component (passed via the
Component { ... } invocation syntax) and as a page function
(registered here). Path / query extraction errors surface as a
Page::Text describing the failure rather than panicking.
§Example
use reinhardt_urls::routers::ClientRouter;
use reinhardt_urls::routers::client_router::from_request::{
ExtractError, FromRequest, PathParam, RouteContext,
};
struct UserPageProps { id: PathParam<i32> }
impl FromRequest for UserPageProps {
fn from_request(ctx: &RouteContext) -> Result<Self, ExtractError> {
Ok(Self { id: PathParam::extract(ctx, "id")? })
}
}
fn user_page(props: UserPageProps) -> reinhardt_core::types::page::Page {
reinhardt_core::types::page::Page::Text(
format!("user {}", props.id.into_inner()).into(),
)
}
let router = ClientRouter::new().page("user", "/users/{id}/", user_page);§Panics
Panics if the pattern is invalid (exceeds length/segment limits
or invalid regex). Use ClientPathPattern::new directly for
fallible construction. Also panics if name duplicates an
already-registered route name.
Sourcepub fn component<F, P>(self, handler: F) -> ClientRouterwhere
F: Fn(P) -> Page + Send + Sync + 'static,
P: FromRequest + ComponentInfo + Send + Sync + 'static,
Available on crate feature pages only.
pub fn component<F, P>(self, handler: F) -> ClientRouterwhere
F: Fn(P) -> Page + Send + Sync + 'static,
P: FromRequest + ComponentInfo + Send + Sync + 'static,
pages only.Adds a named route from metadata generated by #[component].
This mirrors the server-side endpoint registration style: the handler
function supplies the props type, and the props type supplies route
metadata through ComponentInfo.
§Example
use reinhardt_pages::{Page, Path, component, page};
use reinhardt_urls::routers::ClientRouter;
#[component("/users/{id}/", "user-detail")]
fn user_page(Path(id): Path<i64>) -> Page {
page!(|id: i64| { div { { id.to_string() } } })(id)
}
let router = ClientRouter::new().component(user_page);Sourcepub fn guarded_route<F, G>(
self,
pattern: &str,
component: F,
guard: G,
) -> ClientRouter
Available on crate feature pages only.
pub fn guarded_route<F, G>( self, pattern: &str, component: F, guard: G, ) -> ClientRouter
pages only.Adds a route with a guard.
Sourcepub fn route_path<H, Args>(
self,
name: &str,
pattern: &str,
handler: H,
) -> ClientRouterwhere
H: Handler<Args>,
Available on crate feature pages only.
pub fn route_path<H, Args>(
self,
name: &str,
pattern: &str,
handler: H,
) -> ClientRouterwhere
H: Handler<Args>,
pages only.Adds a named route with one to eight path parameters using Path<T>
extractors.
The handler closure may take any number of Path<T> arguments from 1
to 8. The compiler infers the arity from the closure signature via the
sealed Handler<Args> trait, so the same method name covers every
supported arity. Refs Issue #4637.
§Examples
// One path parameter
let router = ClientRouter::new()
.route_path("user_detail", "/users/{id}/", |Path(id): Path<i64>| user_detail(id));
// Two path parameters
let router = router.route_path(
"user_post_detail",
"/users/{user_id}/posts/{post_id}/",
|Path(user_id): Path<i64>, Path(post_id): Path<i64>| {
user_post_detail(user_id, post_id)
},
);
// Three path parameters
let router = router.route_path(
"issue_detail",
"/org/{org}/repos/{repo}/issues/{issue}/",
|Path(org): Path<String>, Path(repo): Path<String>, Path(issue): Path<i32>| {
issue_detail(org, repo, issue)
},
);§Panics
Panics if the pattern is invalid or if name duplicates an
already-registered route name.
Sourcepub fn not_found<F>(self, component: F) -> ClientRouter
Available on crate feature pages only.
pub fn not_found<F>(self, component: F) -> ClientRouter
pages only.Sets the not found handler.
Sourcepub fn current_path(&self) -> &Signal<String>
Available on crate feature pages only.
pub fn current_path(&self) -> &Signal<String>
pages only.Returns the current path signal.
Sourcepub fn current_params(&self) -> &Signal<HashMap<String, String>>
Available on crate feature pages only.
pub fn current_params(&self) -> &Signal<HashMap<String, String>>
pages only.Returns the current params signal.
Sourcepub fn current_route_name(&self) -> &Signal<Option<String>>
Available on crate feature pages only.
pub fn current_route_name(&self) -> &Signal<Option<String>>
pages only.Returns the current route name signal.
Sourcepub fn route_patterns(&self) -> impl Iterator<Item = (&str, Option<&str>)>
Available on crate feature pages only.
pub fn route_patterns(&self) -> impl Iterator<Item = (&str, Option<&str>)>
pages only.Returns an iterator over registered route patterns and their optional names.
Each item is (pattern_str, name) where name is Some for named routes.
Intended for diagnostic output (e.g., the runserver startup banner).
Sourcepub fn match_path(&self, path: &str) -> Option<ClientRouteMatch>
Available on crate feature pages only.
pub fn match_path(&self, path: &str) -> Option<ClientRouteMatch>
pages only.Matches a path against registered routes.
Strips an optional ?query suffix before matching and stores
the captured query (without the leading ?) on
ClientRouteMatch::query. Patterns therefore match against
the path portion only; the query is delivered to handlers via
the match struct (used by ClientRouter::page /
QueryParam).
Sourcepub fn push(&self, path: &str) -> Result<(), RouterError>
Available on crate feature pages only.
pub fn push(&self, path: &str) -> Result<(), RouterError>
pages only.Navigates to a path using pushState.
Sourcepub fn replace(&self, path: &str) -> Result<(), RouterError>
Available on crate feature pages only.
pub fn replace(&self, path: &str) -> Result<(), RouterError>
pages only.Navigates to a path using replaceState.
Available on crate feature pages only.
pages only.Register a listener for navigation events.
Returns a NavigationSubscription handle. Drop the handle to
deregister the listener. The router itself only retains a Weak
reference, so dropping the subscription frees the listener
closure immediately. The stale Weak entry in
navigation_observers is pruned lazily on the next
notify_observers call (the listener itself is already gone by
then).
Robust against nested reactive nodes spawned during view rendering
because this subscription is independent of the reactive
Effect / Signal auto-tracking system.
Mirrors pages::Router::on_navigate. (Refs #4234)
On native targets (Fixes #4258) this is effectively a no-op: the
returned NavigationSubscription is unbound to any observer storage
because reactive observation only fires from the wasm popstate
listener. The method is still callable on native so that the
SpaRouter trait impl in reinhardt-pages (which dispatches into
on_navigate from cross-target launcher code) keeps compiling.
Sourcepub fn reverse(
&self,
name: &str,
params: &[(&str, &str)],
) -> Result<String, RouterError>
Available on crate feature pages only.
pub fn reverse( &self, name: &str, params: &[(&str, &str)], ) -> Result<String, RouterError>
pages only.Generates a URL by route name with parameters.
Sourcepub fn render_current(&self) -> Page
Available on crate feature pages only.
pub fn render_current(&self) -> Page
pages only.Renders the current route’s component.
Returns the registered not_found page when no route matches, or a
default 404 page if no not_found handler has been set.
Sourcepub fn route_count(&self) -> usize
Available on crate feature pages only.
pub fn route_count(&self) -> usize
pages only.Returns the number of registered routes.
Sourcepub fn has_route(&self, name: &str) -> bool
Available on crate feature pages only.
pub fn has_route(&self, name: &str) -> bool
pages only.Checks if a route name exists.
Sourcepub fn setup_history_listener(&self)
Available on native and crate feature pages only.
pub fn setup_history_listener(&self)
native and crate feature pages only.Non-WASM version of setup_history_listener.
Trait Implementations§
Source§impl Clone for ClientRouter
impl Clone for ClientRouter
Source§fn clone(&self) -> ClientRouter
fn clone(&self) -> ClientRouter
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ClientRouter
impl Debug for ClientRouter
Source§impl Default for ClientRouter
impl Default for ClientRouter
Source§fn default() -> ClientRouter
fn default() -> ClientRouter
Auto Trait Implementations§
impl !RefUnwindSafe for ClientRouter
impl !UnwindSafe for ClientRouter
impl Freeze for ClientRouter
impl Send for ClientRouter
impl Sync for ClientRouter
impl Unpin for ClientRouter
impl UnsafeUnpin for ClientRouter
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
type Err = Infallible
fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().Source§impl<E> ServerFnErrorAssertions<E> for Ewhere
E: Debug,
impl<E> ServerFnErrorAssertions<E> for Ewhere
E: Debug,
Source§fn should_contain_message(&self, expected: &str)where
E: Display,
fn should_contain_message(&self, expected: &str)where
E: Display,
Source§fn should_have_message(&self, expected: &str)where
E: Display,
fn should_have_message(&self, expected: &str)where
E: Display,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.