Skip to content

Reactive Route Params

Dioxus component props derived from route parameters (like :contact_id) are plain String values — they don’t trigger reactivity on their own. If you pass a route param directly into a use_resource closure, the resource captures the initial value at mount time and never re-fetches when the user navigates to a different route of the same component.

When MessagingContactView receives a new contact_id from the router, hooks that captured the old value in their closure don’t re-run:

#[component]
pub fn MessagingContactView(contact_id: String) -> Element {
// ❌ Bug: captures contact_id once at mount time.
// Navigating /messaging/abc → /messaging/xyz won't re-fetch.
let contact_resource = use_resource({
let id = contact_id.clone();
move || {
let id = id.clone();
async move { get_contact_api(id).await }
}
});
// ...
}

The component re-renders with the new prop, but use_resource already has its closure bound to the original contact_id.

Wrap the prop in use_memo(use_reactive!(...)) to create a reactive signal that use_resource automatically tracks:

#[component]
pub fn MessagingContactView(contact_id: String) -> Element {
// ✅ Converts a plain String prop into a reactive memo.
// use_reactive! captures contact_id by value and re-emits on change.
// use_memo deduplicates — only triggers downstream when the value actually differs.
let id_memo = use_memo(use_reactive!(|contact_id| contact_id.clone()));
let contact_resource = use_resource(move || {
let id = id_memo();
async move { get_contact_api(id).await }
});
let calls_resource = use_resource(move || {
let id = id_memo();
async move { get_contact_calls_api(id).await }
});
let messages_resource = use_resource(move || {
let id = id_memo();
async move {
let uuid = uuid::Uuid::parse_str(&id)
.map_err(|e| ServerFnError::new(e.to_string()))?;
get_contact_messages_api(uuid).await
}
});
let contact_uuid = uuid::Uuid::parse_str(&id_memo.read()).ok();
// ...
}
  1. use_reactive!(|contact_id| contact_id.clone()) — creates a closure that Dioxus calls whenever the component’s contact_id prop changes. It captures the prop by name and re-emits the new value.

  2. use_memo(...) — wraps the reactive closure in a memoized signal. The memo only notifies subscribers when the value actually changes (deduplication).

  3. use_resource(move || { let id = id_memo(); ... }) — reading id_memo() inside the resource closure subscribes to it. When id_memo updates, all three resources automatically re-run their async fetchers.

Apply use_memo(use_reactive!(...)) whenever a component:

  • Receives a route parameter as a String (or other non-signal) prop
  • Uses that prop inside use_resource, use_effect, or other reactive hooks
  • Stays mounted while the route param changes (same component, different param)
FileRole
src/mods/messaging/views/messaging_contact_view.rsApplies the pattern for contact, calls, and messages resources