#Multiple routes to same components?

1 messages · Page 1 of 1 (latest)

robust glen
#

I would like to have multiple URLs that go to the same component, but I have not found a way to do this directly in the dioxus router. I can do a redirect, but it changes the URL. I want to have separate URLs, they just show the same content. I could create a wrapper component for one of the routes that does nothing but pass the same args to the other component in its rsx, which is certainly a manageable workaround, but I remain curious if this use case is supported in some other approach within the router itself, or expected to be supported in the future. Thanks!

This is especially of interest to me in the context of optional parameters -- the router does not seem to allow for optional params, even tho components allow for it (with Option<...>), and I would like to have different URLs depending on the different params being passed in.

One naive attempted approach:

// redirect works
#[redirect("/oldblog/:id", |id: i32| Route::Blog { id })]
// normal blog route works
#[route("/blog/:id")]
Blog { id: i32 },
// does not compile because this is an enum, we can't list the same value more than once (ofc)
#[route("/otherblog/:id")]
Blog { id: i32 },

But I also cannot do this:

// this compiles but only the first route gets applied to the enum (and how would it even work if it didn't have the same parameters...)
#[route("/otherblog/:id")]
#[route("/blog/:id")]
Blog { id: i32 },

Is there any planned support for optional params, or alternative URLs for the same components, or do I have to just create wrapper components if I want to do either of these?

Thanks!

cosmic herald
#

Enum variants default to rendering a component with the same name as the variant, but you don't have to

#
// normal blog route works
#[route("/blog/:id")]
Blog { id: i32 },
// You can pass a component to render instead of the default
#[route("/otherblog/:id", Blog)]
BlogOther { id: i32 },
#

You can choose to navigate to the variant you want for whichever url form you need

robust glen
#

Oh interesting, I did not see/understand that part -- thank you!

#

That's really fantastic, totally does exactly what I want, and so cleanly!

#[derive(Clone, Routable, Debug, PartialEq)]
enum Route {
    #[route("/")]
    Home {},
    #[route("/blog/:id")]
    Blog { id: i32 },
    #[route("/otherblog/:id", Blog)]
    BlogOther { id: i32 },
    #[route("/noblog", Blog)]
    BlogNone {},
}

#[component]
fn Blog(id: Option<i32>) -> Element {
    rsx! {
        Link { to: Route::Home {}, "Go to counter" }
        if id.is_some() {
            "Blog post {id.unwrap()}"
        } else {
            "Blog post NONE"
        }
    }
}
#

I really enjoy dioxus, thank you ❤️

robust glen
#

@cosmic herald sorry for the necro but I ran into an unexpected case of this. If I change the component to take a ReadOnlySignal<Option<_>> this router breaks:

#[component]
fn Blog(id: ReadOnlySignal<Option<i32>>) -> Element {
    rsx! {
        Link { to: Route::Home {}, "Go to counter" }
        if id().is_some() {
            "Blog post {id.unwrap()}"
        } else {
            "Blog post NONE"
        }
    }
}

Here's the compiler error:

 warning: use of deprecated method `BlogPropsBuilder::<((),)>::build`: Missing required field id
  --> src/main.rs:14:24
   |
14 |     #[route("/noblog", Blog)]
   |                        ^^^^
   |
   = note: `#[warn(deprecated)]` on by default

\ ⚙️ Compiling path+file:///home/chris/git/dioxus/packages/dioxus#0.5.2                                                                                               error[E0061]: this method takes 1 argument but 0 arguments were supplied
  --> src/main.rs:14:24
   |
14 |     #[route("/noblog", Blog)]
   |                        ^^^^ an argument of type `BlogPropsBuilder_Error_Missing_required_field_id` is missing
   |
note: method defined here
  --> src/main.rs:30:1
   |
30 | #[component]
   | ^^^^^^^^^^^^
   = note: this error originates in the derive macro `Props` (in Nightly builds, run with -Z macro-backtrace for more info)
help: provide the argument
   |
14 |     #[route("/noblog", Blog(/* BlogPropsBuilder_Error_Missing_required_field_id */))]

I can work around it by using

    #[route("/noblog", Blog)]
    BlogNone { id: Option<i32> },

And then calling it with

        Link {
            to: Route::BlogNone {
                id: None
            },
            "Go to blog none"
        }

But this all seems more contorted than desirable... Any suggestions? Should this be an issue?

cosmic herald
#

The props macro isn't recognizing the Option inside read only signal to make it optional in the builder

#

Manually telling the props macro that is it optional works:

#[component]
fn Blog(#[props(optional)] id: ReadOnlySignal<Option<i32>>) -> Element {
    rsx! {
        if let Some(id) = id() {
            "Blog post {id}"
        } else {
            "Blog post NONE"
        }
    }
}
robust glen