Skip to main content

Overview

The Navigator type provides programmatic control over navigation and browser history. Use it to navigate between routes, go back/forward, and check navigation state from within components and event handlers.

Getting a Navigator

Using the Hook

use dioxus::prelude::*;

#[derive(Clone, Routable, PartialEq)]
enum Route {
    #[route("/")]
    Home {},
    #[route("/settings")]
    Settings {},
}

#[component]
fn Home() -> Element {
    let navigator = use_navigator();
    
    rsx! {
        button {
            onclick: move |_| {
                navigator.push(Route::Settings {});
            },
            "Go to Settings"
        }
    }
}

#[component]
fn Settings() -> Element {
    rsx! { h1 { "Settings" } }
}

Direct Access

You can also get a navigator without using the hook:
use dioxus_router::navigator;

let nav = navigator();
nav.push(Route::Home {});
Both methods panic if called outside of a Router context.

push

Navigate to a new location, adding it to the history stack:
let navigator = use_navigator();

// Navigate to a route variant
navigator.push(Route::About {});

// Navigate to a path string
navigator.push("/about");

// Navigate to an external URL
navigator.push("https://dioxuslabs.com");
target
impl Into<NavigationTarget>
required
The target to navigate to. Can be:
  • A route enum variant
  • A string path
  • An external URL
Returns: Option<ExternalNavigationFailure> - Returns an error if external navigation is not supported by the current history provider.

replace

Replace the current location without adding to history:
let navigator = use_navigator();

// Replace current route
navigator.replace(Route::Login {});

// User cannot go back to the previous page
target
impl Into<NavigationTarget>
required
The target to navigate to.
Returns: Option<ExternalNavigationFailure>

go_back

Navigate to the previous page in history:
let navigator = use_navigator();

rsx! {
    button {
        onclick: move |_| navigator.go_back(),
        "Back"
    }
}
Fails silently if there is no previous location.

go_forward

Navigate to the next page in history:
let navigator = use_navigator();

rsx! {
    button {
        onclick: move |_| navigator.go_forward(),
        "Forward"
    }
}
Fails silently if there is no next location.

can_go_back

Check if there is a previous page to navigate to:
let navigator = use_navigator();
let can_go_back = navigator.can_go_back();

rsx! {
    button {
        disabled: !can_go_back,
        onclick: move |_| navigator.go_back(),
        "Back"
    }
}
Returns: bool

can_go_forward

Check if there is a next page to navigate to:
let navigator = use_navigator();
let can_go_forward = navigator.can_go_forward();

rsx! {
    button {
        disabled: !can_go_forward,
        onclick: move |_| navigator.go_forward(),
        "Forward"
    }
}
Returns: bool The NavigationTarget enum represents where to navigate:
pub enum NavigationTarget<R = String> {
    Internal(R),      // Internal route
    External(String), // External URL
}
You rarely need to construct these manually, as they’re created automatically from routes and strings:
let navigator = use_navigator();

// These all create NavigationTarget internally:
navigator.push(Route::Home {});           // Internal
navigator.push("/about");                  // Internal
navigator.push("https://example.com");    // External

Common Patterns

#[component]
fn CreatePost() -> Element {
    let navigator = use_navigator();
    let mut title = use_signal(|| String::new());
    
    let submit = move |_| {
        // Save post logic...
        let post_id = 42;
        
        // Navigate to the new post
        navigator.push(Route::Post { id: post_id });
    };
    
    rsx! {
        form { onsubmit: submit,
            input { 
                value: "{title}",
                oninput: move |e| title.set(e.value())
            }
            button { "Create" }
        }
    }
}

Conditional Navigation

#[component]
fn ProtectedPage() -> Element {
    let navigator = use_navigator();
    let is_authenticated = use_signal(|| false);
    
    use_effect(move || {
        if !is_authenticated() {
            navigator.replace(Route::Login {});
        }
    });
    
    rsx! {
        h1 { "Protected Content" }
    }
}
#[component]
fn HistoryControls() -> Element {
    let navigator = use_navigator();
    
    rsx! {
        div { class: "history-controls",
            button {
                disabled: !navigator.can_go_back(),
                onclick: move |_| navigator.go_back(),
                "← Back"
            }
            button {
                disabled: !navigator.can_go_forward(),
                onclick: move |_| navigator.go_forward(),
                "Forward →"
            }
        }
    }
}
#[component]
fn UnsavedChanges() -> Element {
    let navigator = use_navigator();
    let has_unsaved_changes = use_signal(|| true);
    
    let navigate_away = move |_| {
        if has_unsaved_changes() {
            let confirmed = web_sys::window()
                .unwrap()
                .confirm_with_message("You have unsaved changes. Leave anyway?")
                .unwrap();
            
            if confirmed {
                navigator.push(Route::Home {});
            }
        } else {
            navigator.push(Route::Home {});
        }
    };
    
    rsx! {
        button { onclick: navigate_away, "Leave Page" }
    }
}

Redirect After Timeout

#[component]
fn SuccessMessage() -> Element {
    let navigator = use_navigator();
    
    use_effect(move || {
        spawn(async move {
            tokio::time::sleep(Duration::from_secs(3)).await;
            navigator.push(Route::Home {});
        });
    });
    
    rsx! {
        div { class: "success",
            "Success! Redirecting..."
        }
    }
}
The following types can be converted into NavigationTarget:
  • Route enum variants: Route::Home {}
  • String slices: "/about"
  • Strings: String::from("/about")
  • External URLs: "https://example.com"
// All of these work:
navigator.push(Route::Home {});
navigator.push("/about");
navigator.push(String::from("/contact"));
navigator.push("https://dioxuslabs.com");

Error Handling

External navigation may fail if the history provider doesn’t support it:
let navigator = use_navigator();

if let Some(error) = navigator.push("https://example.com") {
    println!("External navigation failed: {:?}", error);
}

Source

View the source code: packages/router/src/contexts/navigator.rs

Build docs developers (and LLMs) love