Kaynağa Gözat

Commit WIP on router

There are a few different changes in here that probably need to be picked
apart. I'm sure much of this is wrong.

* Fix missing `dyn` that compiler complained about in router.rs

* Make UseRoute store a `Rc<RouterService>` rather than a string so we can get
information out of the router like current location.

* Implement `UseRoute`'s nth_segment and last_segment methods. I changed the
return type to a String because of the above.

* Remove some unused imports in platform/mod.rs and service.rs

* Implement the `use_route` fn. It panics if called outside a Router { } (I
think). I think that makes sense.

* Add a `current_location` method to `RouterService` that returns the current
location. I needed this both for the `UseRoute` implementation and _also_ so I
could get at this in my webapp code. I think having some way to get this will
be useful for others, whether or not this exact API is used. In my case, I
want to compare the current path to the `to` path of a `Link` so I can use a
different class for that `Link` if it is the currently active page.
Dave Rolsky 3 yıl önce
ebeveyn
işleme
3c6142f

+ 1 - 1
packages/router/src/components/router.rs

@@ -12,7 +12,7 @@ pub struct RouterProps<'a> {
     children: Element<'a>,
 
     #[props(default, strip_option)]
-    onchange: Option<&'a Fn(&'a str)>,
+    onchange: Option<&'a dyn Fn(&'a str)>,
 }
 
 #[allow(non_snake_case)]

+ 34 - 6
packages/router/src/hooks/use_route.rs

@@ -1,7 +1,11 @@
 use dioxus_core::ScopeState;
+use gloo::history::Location;
+use std::rc::Rc;
+
+use crate::RouterService;
 
 pub struct UseRoute<'a> {
-    cur_route: String,
+    router: Rc<RouterService>,
     cx: &'a ScopeState,
 }
 
@@ -11,20 +15,44 @@ impl<'a> UseRoute<'a> {
         todo!()
     }
 
-    pub fn nth_segment(&self, n: usize) -> Option<&str> {
-        todo!()
+    pub fn nth_segment(&self, n: usize) -> Option<String> {
+        let mut segments = self.path_segments();
+        let len = segments.len();
+        if len - 1 < n {
+            return None;
+        }
+        Some(segments.remove(n))
     }
 
-    pub fn last_segment(&self) -> Option<&'a str> {
-        todo!()
+    pub fn last_segment(&self) -> Option<String> {
+        let mut segments = self.path_segments();
+        let len = segments.len();
+        if len == 0 {
+            return None;
+        }
+        Some(segments.remove(len - 1))
     }
 
     /// Parse the segments of the URL, using named parameters (defined in your router)
     pub fn segment<T>(&self, name: &str) -> Option<&T> {
         todo!()
     }
+
+    pub fn current_location(&self) -> Location {
+        self.router.current_location()
+    }
+
+    fn path_segments(&self) -> Vec<String> {
+        let location = self.router.current_location();
+        let stripped = &location.path()[1..];
+        stripped.split('/').map(str::to_string).collect::<Vec<_>>()
+    }
 }
 
 pub fn use_route<'a>(cx: &'a ScopeState) -> UseRoute<'a> {
-    todo!()
+    let router = cx
+        .consume_context::<RouterService>()
+        .expect("Cannot call use_route outside the scope of a Router component")
+        .clone();
+    UseRoute { router, cx }
 }

+ 0 - 2
packages/router/src/platform/mod.rs

@@ -1,5 +1,3 @@
-use url::Url;
-
 pub trait RouterProvider {
     fn get_current_route(&self) -> String;
     fn subscribe_to_route_changes(&self, callback: Box<dyn Fn(String)>);

+ 5 - 2
packages/router/src/service.rs

@@ -1,7 +1,6 @@
-use gloo::history::{BrowserHistory, History, HistoryListener};
+use gloo::history::{BrowserHistory, History, HistoryListener, Location};
 use std::{
     cell::{Cell, RefCell},
-    collections::HashMap,
     rc::Rc,
 };
 
@@ -118,6 +117,10 @@ impl RouterService {
             None => false,
         }
     }
+
+    pub fn current_location(&self) -> Location {
+        self.history.borrow().location().clone()
+    }
 }
 
 pub struct RouterCfg {