mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 04:33:06 +00:00
Merge pull request #158 from DioxusLabs/jk/router-onchange
Connect the onchange listener for the Router
This commit is contained in:
commit
08988e1bfe
4 changed files with 42 additions and 30 deletions
|
@ -5,7 +5,7 @@ DioxusRouter adds React-Router style routing to your Dioxus apps. Works in brows
|
|||
```rust
|
||||
fn app() {
|
||||
cx.render(rsx! {
|
||||
Routes {
|
||||
Router {
|
||||
Route { to: "/", Component {} },
|
||||
Route { to: "/blog", Blog {} },
|
||||
Route { to: "/blog/:id", BlogPost {} },
|
||||
|
|
|
@ -11,17 +11,26 @@ use crate::RouterService;
|
|||
pub struct RouterProps<'a> {
|
||||
children: Element<'a>,
|
||||
|
||||
#[props(default, strip_option)]
|
||||
onchange: Option<&'a dyn Fn(&'a str)>,
|
||||
#[props(default)]
|
||||
onchange: EventHandler<'a, String>,
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Router<'a>(cx: Scope<'a, RouterProps<'a>>) -> Element {
|
||||
cx.use_hook(|_| {
|
||||
let svc = cx.use_hook(|_| {
|
||||
let update = cx.schedule_update_any();
|
||||
cx.provide_context(RouterService::new(update, cx.scope_id()))
|
||||
});
|
||||
|
||||
let any_pending = svc.pending_events.borrow().len() > 0;
|
||||
svc.pending_events.borrow_mut().clear();
|
||||
|
||||
if any_pending {
|
||||
let location = svc.current_location();
|
||||
let path = location.path();
|
||||
cx.props.onchange.call(path.to_string());
|
||||
}
|
||||
|
||||
cx.render(rsx!(
|
||||
div { &cx.props.children }
|
||||
))
|
||||
|
|
|
@ -8,22 +8,9 @@
|
|||
//!
|
||||
//! ```rust
|
||||
//! fn app(cx: Scope) -> Element {
|
||||
//!
|
||||
//! }
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
//!
|
||||
|
||||
mod hooks {
|
||||
mod use_route;
|
||||
|
|
|
@ -9,6 +9,7 @@ use dioxus_core::ScopeId;
|
|||
|
||||
pub struct RouterService {
|
||||
pub(crate) regen_route: Rc<dyn Fn(ScopeId)>,
|
||||
pub(crate) pending_events: Rc<RefCell<Vec<RouteEvent>>>,
|
||||
history: Rc<RefCell<BrowserHistory>>,
|
||||
slots: Rc<RefCell<Vec<(ScopeId, String)>>>,
|
||||
root_found: Rc<Cell<Option<ScopeId>>>,
|
||||
|
@ -16,6 +17,12 @@ pub struct RouterService {
|
|||
listener: HistoryListener,
|
||||
}
|
||||
|
||||
pub enum RouteEvent {
|
||||
Change,
|
||||
Pop,
|
||||
Push,
|
||||
}
|
||||
|
||||
enum RouteSlot {
|
||||
Routes {
|
||||
// the partial route
|
||||
|
@ -36,28 +43,37 @@ impl RouterService {
|
|||
let path = location.path();
|
||||
|
||||
let slots: Rc<RefCell<Vec<(ScopeId, String)>>> = Default::default();
|
||||
|
||||
let _slots = slots.clone();
|
||||
|
||||
let pending_events: Rc<RefCell<Vec<RouteEvent>>> = Default::default();
|
||||
let root_found = Rc::new(Cell::new(None));
|
||||
let regen = regen_route.clone();
|
||||
let _root_found = root_found.clone();
|
||||
let listener = history.listen(move || {
|
||||
_root_found.set(None);
|
||||
|
||||
let listener = history.listen({
|
||||
let pending_events = pending_events.clone();
|
||||
let regen_route = regen_route.clone();
|
||||
let root_found = root_found.clone();
|
||||
let slots = slots.clone();
|
||||
move || {
|
||||
root_found.set(None);
|
||||
// checking if the route is valid is cheap, so we do it
|
||||
for (slot, root) in _slots.borrow_mut().iter().rev() {
|
||||
for (slot, root) in slots.borrow_mut().iter().rev() {
|
||||
log::trace!("regenerating slot {:?} for root '{}'", slot, root);
|
||||
regen(*slot);
|
||||
regen_route(*slot);
|
||||
}
|
||||
|
||||
// also regenerate the root
|
||||
regen_route(root_scope);
|
||||
|
||||
pending_events.borrow_mut().push(RouteEvent::Change)
|
||||
}
|
||||
});
|
||||
|
||||
Self {
|
||||
listener,
|
||||
root_found,
|
||||
history: Rc::new(RefCell::new(history)),
|
||||
regen_route,
|
||||
slots,
|
||||
pending_events,
|
||||
cur_path_params: Rc::new(RefCell::new(HashMap::new())),
|
||||
listener,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue