use_route.rs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. use dioxus_core::ScopeState;
  2. use gloo::history::{HistoryResult, Location};
  3. use serde::de::DeserializeOwned;
  4. use std::{rc::Rc, str::FromStr};
  5. use crate::RouterService;
  6. /// This struct provides is a wrapper around the internal router
  7. /// implementation, with methods for getting information about the current
  8. /// route.
  9. pub struct UseRoute {
  10. router: Rc<RouterService>,
  11. }
  12. impl UseRoute {
  13. /// This method simply calls the [`Location::query`] method.
  14. pub fn query<T>(&self) -> HistoryResult<T>
  15. where
  16. T: DeserializeOwned,
  17. {
  18. self.current_location().query::<T>()
  19. }
  20. /// Returns the nth segment in the path. Paths that end with a slash have
  21. /// the slash removed before determining the segments. If the path has
  22. /// fewer segments than `n` then this method returns `None`.
  23. pub fn nth_segment(&self, n: usize) -> Option<String> {
  24. let mut segments = self.path_segments();
  25. let len = segments.len();
  26. if len - 1 < n {
  27. return None;
  28. }
  29. Some(segments.remove(n))
  30. }
  31. /// Returns the last segment in the path. Paths that end with a slash have
  32. /// the slash removed before determining the segments. The root path, `/`,
  33. /// will return an empty string.
  34. pub fn last_segment(&self) -> String {
  35. let mut segments = self.path_segments();
  36. segments.remove(segments.len() - 1)
  37. }
  38. /// Get the named parameter from the path, as defined in your router. The
  39. /// value will be parsed into the type specified by `T` by calling
  40. /// `value.parse::<T>()`. This method returns `None` if the named
  41. /// parameter does not exist in the current path.
  42. pub fn segment<T>(&self, name: &str) -> Option<Result<T, T::Err>>
  43. where
  44. T: FromStr,
  45. {
  46. self.router
  47. .current_path_params()
  48. .get(name)
  49. .and_then(|v| Some(v.parse::<T>()))
  50. }
  51. /// Returns the [Location] for the current route.
  52. pub fn current_location(&self) -> Location {
  53. self.router.current_location()
  54. }
  55. fn path_segments(&self) -> Vec<String> {
  56. let location = self.router.current_location();
  57. let path = location.path();
  58. if path == "/" {
  59. return vec![String::new()];
  60. }
  61. let stripped = &location.path()[1..];
  62. stripped.split('/').map(str::to_string).collect::<Vec<_>>()
  63. }
  64. }
  65. /// This hook provides access to information about the current location in the
  66. /// context of a [`Router`]. If this function is called outside of a `Router`
  67. /// component it will panic.
  68. pub fn use_route(cx: &ScopeState) -> UseRoute {
  69. let router = cx
  70. .consume_context::<RouterService>()
  71. .expect("Cannot call use_route outside the scope of a Router component")
  72. .clone();
  73. UseRoute { router }
  74. }