dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

Dioxus Router’s `on_update` callback is not called when using browser’s back/forward buttons

Open iggyzuk opened this issue 2 years ago • 1 comments

Problem

Router's on_update callback is not called when going back or forward using the browser's buttons, it only works when you click on links.

Steps To Reproduce

  • Create a project using the code below
  • In terminal dx serve
  • In browser go to localhost:8080
  • Open developer tools > console
  • Click on a link – notice the message works: "--- route update ---"
  • Go back using the browser key – notice no message now
  • Go forward using the browser key – notice no message either

Expected behavior

on_update should be called when clicking on links and using the browser's back and forward buttons.

Environment:

  • Dioxus version: [0.4.0]
  • Dx serve version: [0.4.1]
  • Rust version: [1.73.0]
  • OS info: [MacOS]
  • App platform: [web]

Code

Use the example code and add a log in the RouterConfig::on_update.

#![allow(non_snake_case)]

use dioxus::prelude::*;
use dioxus_router::prelude::*;

// ANCHOR: router
#[derive(Routable, Clone)]
#[rustfmt::skip]
enum Route {
    #[layout(NavBar)]
        #[route("/")]
        Home {},
        #[nest("/blog")]
            #[layout(Blog)]
                #[route("/")]
                BlogList {},
                #[route("/post/:name")]
                BlogPost { name: String },
            #[end_layout]
        #[end_nest]
    #[end_layout]
    #[nest("/myblog")]
        #[redirect("/", || Route::BlogList {})]
        #[redirect("/:name", |name: String| Route::BlogPost { name })]
    #[end_nest]
    #[route("/:..route")]
    PageNotFound {
        route: Vec<String>,
    },
}
// ANCHOR_END: router

pub fn App(cx: Scope) -> Element {
    render! {
        Router::<Route> {
            config: move || RouterConfig::default()
            .on_update(move |_| {
                log::info!("--- route update ---");
                None
            })
        }
    }
}

#[inline_props]
fn NavBar(cx: Scope) -> Element {
    render! {
        nav {
            ul {
                li { Link { to: Route::Home {}, "Home" } }
                li { Link { to: Route::BlogList {}, "Blog" } }
            }
        }
        Outlet::<Route> {}
    }
}

#[inline_props]
fn Home(cx: Scope) -> Element {
    render! {
        h1 { "Welcome to the Dioxus Blog!" }
    }
}

#[inline_props]
fn Blog(cx: Scope) -> Element {
    render! {
        h1 { "Blog" }
        Outlet::<Route> {}
    }
}

#[inline_props]
fn BlogList(cx: Scope) -> Element {
    render! {
        h2 { "Choose a post" }
        ul {
            li {
                Link {
                    to: Route::BlogPost { name: "Blog post 1".into() },
                    "Read the first blog post"
                }
            }
            li {
                Link {
                    to: Route::BlogPost { name: "Blog post 2".into() },
                    "Read the second blog post"
                }
            }
        }
    }
}

#[inline_props]
fn BlogPost(cx: Scope, name: String) -> Element {
    render! {
        h2 { "Blog Post: {name}"}
    }
}

#[inline_props]
fn PageNotFound(cx: Scope, route: Vec<String>) -> Element {
    render! {
        h1 { "Page not found" }
        p { "We are terribly sorry, but the page you requested doesn't exist." }
        pre {
            color: "red",
            "log:\nattemped to navigate to: {route:?}"
        }
    }
}

fn main() {
    dioxus_logger::init(log::LevelFilter::Trace).expect("failed to init logger");
    dioxus_web::launch(App);
}
[dependencies]
dioxus = "0.4.0"
dioxus-web = "0.4.0"
dioxus-router = "0.4.1"
dioxus-logger = "0.4.1"
log = "0.4.20"

iggyzuk avatar Nov 22 '23 11:11 iggyzuk

This issue is still present in 0.5. Here is an updated reproduction:

#![allow(non_snake_case)]

use dioxus::prelude::*;

#[derive(Routable, Clone)]
#[rustfmt::skip]
enum Route {
    #[layout(NavBar)]
        #[route("/")]
        Home {},
        #[nest("/blog")]
            #[layout(Blog)]
                #[route("/")]
                BlogList {},
                #[route("/post/:name")]
                BlogPost { name: String },
            #[end_layout]
        #[end_nest]
    #[end_layout]
    #[nest("/myblog")]
        #[redirect("/", || Route::BlogList {})]
        #[redirect("/:name", |name: String| Route::BlogPost { name })]
    #[end_nest]
    #[route("/:..route")]
    PageNotFound {
        route: Vec<String>,
    },
}

pub fn App() -> Element {
    rsx! {
        Router::<Route> {
            config: move || RouterConfig::default()
            .on_update(move |_| {
                tracing::info!("--- route update ---");
                None
            })
        }
    }
}

#[component]
fn NavBar() -> Element {
    rsx! {
        nav {
            ul {
                li { Link { to: Route::Home {}, "Home" } }
                li { Link { to: Route::BlogList {}, "Blog" } }
            }
        }
        Outlet::<Route> {}
    }
}

#[component]
fn Home() -> Element {
    rsx! {
        h1 { "Welcome to the Dioxus Blog!" }
    }
}

#[component]
fn Blog() -> Element {
    rsx! {
        h1 { "Blog" }
        Outlet::<Route> {}
    }
}

#[component]
fn BlogList() -> Element {
    rsx! {
        h2 { "Choose a post" }
        ul {
            li {
                Link {
                    to: Route::BlogPost { name: "Blog post 1".into() },
                    "Read the first blog post"
                }
            }
            li {
                Link {
                    to: Route::BlogPost { name: "Blog post 2".into() },
                    "Read the second blog post"
                }
            }
        }
    }
}

#[component]
fn BlogPost(name: String) -> Element {
    rsx! {
        h2 { "Blog Post: {name}"}
    }
}

#[component]
fn PageNotFound(route: Vec<String>) -> Element {
    rsx! {
        h1 { "Page not found" }
        p { "We are terribly sorry, but the page you requested doesn't exist." }
        pre {
            color: "red",
            "log:\nattemped to navigate to: {route:?}"
        }
    }
}

fn main() {
    dioxus_logger::init(tracing::Level::TRACE).expect("failed to init logger");
    launch(App);
}

ealmloff avatar Jun 11 '24 14:06 ealmloff