dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

Change dioxus_router to require explicitly setting components to be used

Open Freyja-moth opened this issue 9 months ago • 8 comments

Feature Request

The current implementation of the Routable macro pulls in components from the namespace by default.

However this can make it quite unclear what is being used and forces users to keep names consistent between the components and routers.

This can also mess with people ide's workflows, as many people (myself included) have binds for going to the definition of something or renaming all instances of a identity.

#[rustfmt::skip]
#[derive(Clone, Debug, PartialEq, Routable)]
enum Route {
    #[nest("/blog")]
        #[layout(Blog)]
            #[route("/")]
            BlogList {},

            #[route("/:blog_id")]
            BlogPost { blog_id: usize },
        #[end_layout]
    #[end_nest]
    #[route("/")]
    Index {},
}

Implement Suggestion

Force the explicit use of components in for each route of the router instead of implicitly finding them in the namespace, in order to make it clearer what's being used and to stop namespace collisions.

#[rustfmt::skip]
#[derive(Clone, Debug, PartialEq, Routable)]
enum Route {
    #[nest("/blog")]
        #[layout(Blog)]
            #[route("/", BlogList)]
            BlogList {},

            #[route("/:blog_id", BlogPost)]
            BlogPost { blog_id: usize },
        #[end_layout]
    #[end_nest]
    #[route("/", Home)]
    Index {},
}

Freyja-moth avatar Apr 08 '25 13:04 Freyja-moth

For reference bevy uses a similar idea in their relationship macros.

#[derive(Component)]
#[relationship_target(relationship = ChildOf)]
pub struct Children(Vec<Entity);

Freyja-moth avatar Apr 08 '25 13:04 Freyja-moth

Perhaps this could even be extended to accept a closure that takes in whatever arguments are specified by the enum variant, such as

#[rustfmt::skip]
#[derive(Clone, Debug, PartialEq, Routable)]
enum Route {
    // Obviously there's not much point to doing it here, but it would allow people to do complex conversions that can't be done with FromStr such as composing data from multiple variables
    #[route("/post/:post_id")]
    #[route_component(|id| rsx!{
        Post { id: id }
    })]
    Post { post_id: usize },
        
    #[route("/")]
    #[route_component(Home)]
    Index {},
}

Though I may just be getting ahead of myself

Freyja-moth avatar Apr 08 '25 14:04 Freyja-moth

Didn't see it documented, but looking at the macro it seems route does allow an optional second argument for the component. https://github.com/DioxusLabs/dioxus/blob/4f74ef81d1225829d92440bd7da6861045a4738a/packages/router-macro/src/route.rs#L33-L36

I'm afk, but it seems like #[route("/", Home)] should do what you need.

pandarrr avatar Apr 08 '25 19:04 pandarrr

Ah right, in that case it's probably a good idea to point it out. I'd still recommend reworking it so that it's required since the current default way feels very unstable but it's good to know there is a way to do this

Freyja-moth avatar Apr 08 '25 19:04 Freyja-moth

Nvm, it is documented in the router macro crate. https://docs.rs/dioxus-router-macro/latest/dioxus_router_macro/derive.Routable.html

Visibility could be better that's true.

pandarrr avatar Apr 08 '25 19:04 pandarrr

The closure feature I pointed out seems to be documented there as well which is cool.

Freyja-moth avatar Apr 08 '25 19:04 Freyja-moth

Oh no that's for redirects

Freyja-moth avatar Apr 08 '25 19:04 Freyja-moth

Yeah, but given it already exists for redirects it doesn't seem like a stretch to add it for normal routes too.

If the team wants it I could give it a go. Making the component required would be breaking so that's up to them to decide if and when, but maybe we could add a clippy warning or something allowing you to opt-in to that enforcement.

pandarrr avatar Apr 09 '25 00:04 pandarrr