Skip to main content

freya_router/components/
router.rs

1use freya_core::prelude::*;
2
3use crate::{
4    prelude::{
5        Outlet,
6        OutletContext,
7        RouterContext,
8    },
9    routable::Routable,
10    router_cfg::RouterConfig,
11};
12
13pub struct Router<R: Routable + Clone>(NoArgCallback<RouterConfig<R>>);
14
15impl<R: Routable + Clone> PartialEq for Router<R> {
16    fn eq(&self, other: &Self) -> bool {
17        self.0 == other.0
18    }
19}
20
21impl<R: Routable + Clone> Router<R> {
22    pub fn new(init: impl Into<NoArgCallback<RouterConfig<R>>>) -> Self {
23        Self(init.into())
24    }
25}
26
27impl<R: Routable + Clone> Component for Router<R> {
28    fn render(&self) -> impl IntoElement {
29        use_hook(|| {
30            // Only create contexts if they don't already exist in this scope.
31            // On hot-reload, `reset_hooks` clears hook values but preserves contexts,
32            // so unconditionally calling `provide_context` would overwrite the
33            // existing RouterContext and reset navigation state to the initial path.
34            if try_consume_own_context::<RouterContext>().is_none() {
35                provide_context(RouterContext::create::<R>(self.0.call()));
36            }
37            if try_consume_own_context::<OutletContext<R>>().is_none() {
38                provide_context(OutletContext::<R>::new());
39            }
40        });
41
42        Outlet::<R>::new()
43    }
44}
45
46pub fn use_share_router(router: impl FnOnce() -> RouterContext) {
47    use_provide_context(router);
48}