router.rs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. use dioxus_lib::prelude::*;
  2. use std::{cell::RefCell, rc::Rc, str::FromStr};
  3. use crate::{prelude::Outlet, routable::Routable, router_cfg::RouterConfig};
  4. /// The config for [`Router`].
  5. #[derive(Clone)]
  6. pub struct RouterConfigFactory<R: Routable> {
  7. #[allow(clippy::type_complexity)]
  8. config: Rc<RefCell<Option<Box<dyn FnOnce() -> RouterConfig<R>>>>>,
  9. }
  10. impl<R: Routable> Default for RouterConfigFactory<R>
  11. where
  12. <R as FromStr>::Err: std::fmt::Display,
  13. {
  14. fn default() -> Self {
  15. Self::from(RouterConfig::default)
  16. }
  17. }
  18. impl<R: Routable, F: FnOnce() -> RouterConfig<R> + 'static> From<F> for RouterConfigFactory<R> {
  19. fn from(value: F) -> Self {
  20. Self {
  21. config: Rc::new(RefCell::new(Some(Box::new(value)))),
  22. }
  23. }
  24. }
  25. /// The props for [`Router`].
  26. #[derive(Props)]
  27. pub struct RouterProps<R: Routable>
  28. where
  29. <R as FromStr>::Err: std::fmt::Display,
  30. {
  31. #[props(default, into)]
  32. config: RouterConfigFactory<R>,
  33. }
  34. impl<T: Routable> Clone for RouterProps<T>
  35. where
  36. <T as FromStr>::Err: std::fmt::Display,
  37. {
  38. fn clone(&self) -> Self {
  39. Self {
  40. config: self.config.clone(),
  41. }
  42. }
  43. }
  44. impl<R: Routable> Default for RouterProps<R>
  45. where
  46. <R as FromStr>::Err: std::fmt::Display,
  47. {
  48. fn default() -> Self {
  49. Self {
  50. config: RouterConfigFactory::default(),
  51. }
  52. }
  53. }
  54. impl<R: Routable> PartialEq for RouterProps<R>
  55. where
  56. <R as FromStr>::Err: std::fmt::Display,
  57. {
  58. fn eq(&self, _: &Self) -> bool {
  59. // prevent the router from re-rendering when the initial url or config changes
  60. true
  61. }
  62. }
  63. /// A component that renders the current route.
  64. pub fn Router<R: Routable + Clone>(props: RouterProps<R>) -> Element
  65. where
  66. <R as FromStr>::Err: std::fmt::Display,
  67. {
  68. use crate::prelude::{outlet::OutletContext, RouterContext};
  69. use_hook(|| {
  70. provide_context(RouterContext::new(
  71. (props
  72. .config
  73. .config
  74. .take()
  75. .expect("use_context_provider ran twice"))(),
  76. schedule_update_any(),
  77. ));
  78. provide_context(OutletContext::<R> {
  79. current_level: 0,
  80. _marker: std::marker::PhantomData,
  81. });
  82. });
  83. rsx! { Outlet::<R> {} }
  84. }