Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DioxusLabs/dioxus/llms.txt

Use this file to discover all available pages before exploring further.

Dioxus routes can extract data from URLs through path segments, query parameters, and hash fragments. All parameters are type-safe and automatically parsed.

Path Parameters

Path parameters are dynamic segments in the URL path, prefixed with : in route definitions.

Single Parameter

use dioxus::prelude::*;

#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/user/:id")]
    User { id: usize },
}

#[component]
fn User(id: usize) -> Element {
    rsx! { h1 { "User {id}" } }
}
URL /user/123 extracts id = 123.

Multiple Parameters

#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/blog/:year/:month/:slug")]
    BlogPost {
        year: u32,
        month: u32,
        slug: String,
    },
}

#[component]
fn BlogPost(year: u32, month: u32, slug: String) -> Element {
    rsx! {
        h1 { "{slug}" }
        p { "Published: {month}/{year}" }
    }
}
URL /blog/2024/03/hello-world extracts:
  • year = 2024
  • month = 3
  • slug = "hello-world"

Supported Types

Path parameters can be any type implementing FromStr:
#[route("/user/:id")]
User { id: usize },         // Numbers

#[route("/post/:slug")]
Post { slug: String },      // Strings

#[route("/active/:enabled")]
Filter { enabled: bool },   // Booleans

#[route("/uuid/:id")]
Item { id: Uuid },          // Custom types with FromStr

Custom Types

Implement FromStr and Display for custom types:
use std::fmt;
use std::str::FromStr;

#[derive(Clone, PartialEq, Debug)]
struct UserId(usize);

impl FromStr for UserId {
    type Err = std::num::ParseIntError;
    
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(UserId(s.parse()?))
    }
}

impl fmt::Display for UserId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

// Use in route
#[route("/user/:id")]
User { id: UserId },

Parse Errors

If parsing fails, the route doesn’t match and the router tries the next route:
#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/user/:id")]
    User { id: usize },      // Only matches numeric IDs
    
    #[route("/:..path")]
    NotFound { path: Vec<String> },  // Catches failed parses
}
URL /user/abc won’t match User (parse error), falls through to NotFound.

Catch-All Parameters

Capture multiple path segments with :..name:
#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/files/:..path")]
    Files { path: Vec<String> },
}

#[component]
fn Files(path: Vec<String>) -> Element {
    let full_path = path.join("/");
    rsx! { h1 { "File: {full_path}" } }
}
URL /files/docs/2024/report.pdf extracts:
  • path = vec!["docs", "2024", "report.pdf"]

404 Pages

Catch-all routes are perfect for 404 pages:
#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/")]
    Home {},
    
    // Catches all unmatched routes
    #[route("/:..path")]
    NotFound { path: Vec<String> },
}

#[component]
fn NotFound(path: Vec<String>) -> Element {
    rsx! {
        h1 { "404: Page Not Found" }
        p { "Could not find: /{path:?}" }
        Link { to: Route::Home {}, "Go Home" }
    }
}
Place catch-all routes last in your enum to avoid matching more specific routes.

Query Parameters

Query parameters are extracted from the URL query string after ?.

Single Query Parameter

#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/search?:q")]
    Search { q: String },
}

#[component]
fn Search(q: String) -> Element {
    rsx! {
        h1 { "Search Results" }
        p { "Query: {q}" }
    }
}
URL /search?q=rust extracts q = "rust".

Multiple Query Parameters

#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/products?:category&:sort&:page")]
    Products {
        category: String,
        sort: String,
        page: usize,
    },
}
URL /products?category=books&sort=price&page=2 extracts:
  • category = "books"
  • sort = "price"
  • page = 2

Optional Query Parameters

Use Option<T> for optional parameters:
#[derive(Routable, Clone, PartialEq, Debug)]
enum Route {
    #[route("/search?:q&:page")]
    Search {
        q: String,
        page: Option<usize>,  // Optional parameter
    },
}

#[component]
fn Search(q: String, page: Option<usize>) -> Element {
    let page_num = page.unwrap_or(1);
    rsx! {
        h1 { "Search: {q}" }
        p { "Page {page_num}" }
    }
}
Both URLs work:
  • /search?q=rustq = "rust", page = None
  • /search?q=rust&page=2q = "rust", page = Some(2)

Default Values

Query parameter types must implement Default:
#[derive(Clone, PartialEq, Debug)]
struct SearchOptions {
    sort_by: String,
}

impl Default for SearchOptions {
    fn default() -> Self {
        Self {
            sort_by: "relevance".to_string(),
        }
    }
}

impl FromStr for SearchOptions {
    type Err = String;
    
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self { sort_by: s.to_string() })
    }
}

impl fmt::Display for SearchOptions {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.sort_by)
    }
}

Catch-All Query String

Capture the entire query string with ?:..name:
#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/search?:..query")]
    Search { query: String },
}

#[component]
fn Search(query: String) -> Element {
    // Parse custom query format
    rsx! { p { "Raw query: {query}" } }
}
URL /search?foo=bar&baz=quxquery = "foo=bar&baz=qux"

Reactive Query Parameters

Use ReadSignal to make parameters reactive:
#[component]
fn Search(q: ReadSignal<String>, page: ReadSignal<usize>) -> Element {
    // Automatically recomputes when q or page changes
    let results = use_memo(move || {
        fetch_results(&q.read(), page())
    });
    
    rsx! {
        input {
            value: "{q}",
            oninput: move |e| {
                navigator().replace(Route::Search {
                    q: e.value(),
                    page: page(),
                });
            }
        }
        // Display results
    }
}
See the query_segment_search example for a full implementation.

Hash Fragments

Capture URL hash fragments (anchor links) with #:name:
#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/docs#:section")]
    Docs { section: String },
}

#[component]
fn Docs(section: String) -> Element {
    use_effect(move || {
        // Scroll to section
        if let Some(element) = document().get_element_by_id(&section) {
            element.scroll_into_view();
        }
    });
    
    rsx! {
        h1 { "Documentation" }
        div { id: "introduction", "Introduction..." }
        div { id: "installation", "Installation..." }
    }
}
URL /docs#installation extracts section = "installation".

Hash Fragment State

Store application state in the hash:
#[derive(Clone, PartialEq, Default, Debug)]
struct AppState {
    count: usize,
}

impl fmt::Display for AppState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "count:{}", self.count)
    }
}

impl FromStr for AppState {
    type Err = String;
    
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let count = s.strip_prefix("count:")
            .and_then(|s| s.parse().ok())
            .unwrap_or(0);
        Ok(AppState { count })
    }
}

#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/app#:state")]
    App { state: AppState },
}

Combining Parameters

Mix path, query, and hash parameters:
#[derive(Routable, Clone, PartialEq)]
enum Route {
    #[route("/blog/:slug?:highlight#:section")]
    BlogPost {
        slug: String,           // Path parameter
        highlight: String,      // Query parameter
        section: String,        // Hash fragment
    },
}
URL /blog/my-post?highlight=code#comments extracts:
  • slug = "my-post"
  • highlight = "code"
  • section = "comments"
rsx! {
    Link {
        to: Route::User { id: 123 },
        "View User"
    }
    Link {
        to: Route::Search {
            q: "rust".to_string(),
            page: Some(2),
        },
        "Search Results"
    }
}

Using Navigator

let nav = use_navigator();

rsx! {
    button {
        onclick: move |_| {
            nav.push(Route::BlogPost {
                year: 2024,
                month: 3,
                slug: "new-post".to_string(),
            });
        },
        "View Post"
    }
}

URL Encoding

Parameters are automatically URL encoded/decoded:
#[route("/search?:q")]
Search { q: String },
  • "hello world"/search?q=hello%20world
  • /search?q=hello%20worldq = "hello world"
Special characters are handled automatically:
Link {
    to: Route::Search { q: "hello & goodbye".to_string() },
    "Search"
}
// Generates: /search?q=hello%20%26%20goodbye

Type Safety Benefits

The enum router provides compile-time guarantees:
// ✅ Compiles - all parameters provided
Link { to: Route::User { id: 123 }, "User" }

// ❌ Compile error - missing parameter
Link { to: Route::User {}, "User" }

// ❌ Compile error - wrong type
Link { to: Route::User { id: "abc" }, "User" }
Compare with string-based routing:
// All compile, but some are wrong!
<a href="/user/123">User</a>      // ✅ Correct
<a href="/user">User</a>          // ❌ Missing ID - broken link
<a href="/user/abc">User</a>      // ❌ Invalid ID - runtime error

Accessing Current Route

Get the current route with use_route():
#[component]
fn MyComponent() -> Element {
    let route = use_route::<Route>();
    
    match route {
        Route::User { id } => rsx! { p { "Viewing user {id}" } },
        Route::Home {} => rsx! { p { "On home page" } },
        _ => rsx! { p { "Other page" } },
    }
}

Best Practices

  1. Use specific types - usize instead of String for IDs
  2. Validate in components - Don’t trust that parameters are valid
  3. Provide defaults - Use Option or Default for optional params
  4. Keep URLs readable - Use descriptive parameter names
  5. Encode special characters - Let the router handle encoding

Common Patterns

Pagination

#[route("/products?:page")]
Products { page: Option<usize> },

#[component]
fn Products(page: Option<usize>) -> Element {
    let current_page = page.unwrap_or(1);
    
    rsx! {
        Link {
            to: Route::Products { page: Some(current_page + 1) },
            "Next Page"
        }
    }
}

Filtering

#[route("/products?:category&:min_price&:max_price")]
Products {
    category: Option<String>,
    min_price: Option<f64>,
    max_price: Option<f64>,
},
#[route("/docs/:..path")]
Docs { path: Vec<String> },

#[component]
fn Docs(path: Vec<String>) -> Element {
    rsx! {
        nav {
            Link { to: Route::Docs { path: vec![] }, "Docs" }
            for (i, segment) in path.iter().enumerate() {
                " / "
                Link {
                    to: Route::Docs {
                        path: path[..=i].to_vec()
                    },
                    "{segment}"
                }
            }
        }
    }
}

Build docs developers (and LLMs) love