dioxus_lib::prelude

Function onmounted

source
pub fn onmounted<__Marker>(
    _f: impl SuperInto<Callback<Event<MountedData>>, __Marker>,
) -> Attribute
Expand description

The onmounted event is fired when the element is first added to the DOM. This event gives you a MountedData object and lets you interact with the raw DOM element.

This event is fired once per element. If you need to access the element multiple times, you can store the MountedData object in a [use_signal] hook and use it as needed.

§Examples

fn App() -> Element {
    let mut header_element = use_signal(|| None);

    rsx! {
        div {
            h1 {
                // The onmounted event will run the first time the h1 element is mounted
                onmounted: move |element| header_element.set(Some(element.data())),
                "Scroll to top example"
            }

            for i in 0..100 {
                div { "Item {i}" }
            }

            button {
                // When you click the button, if the header element has been mounted, we scroll to that element
                onclick: move |_| async move {
                    if let Some(header) = header_element.cloned() {
                        let _ = header.scroll_to(ScrollBehavior::Smooth).await;
                    }
                },
                "Scroll to top"
            }
        }
    }
}

The MountedData struct contains cross platform APIs that work on the desktop, mobile, liveview and web platforms. For the web platform, you can also downcast the MountedData event to the web-sys::Element type for more web specific APIs:

fn App() -> Element {
    rsx! {
        div {
            id: "some-id",
            onmounted: move |element| {
                // You can use the web_event trait to downcast the element to a web specific event. For the mounted event, this will be a web_sys::Element
                let web_sys_element = element.as_web_event();
                assert_eq!(web_sys_element.id(), "some-id");
            }
        }
    }
}
General Event Handler Information

§Event Handlers

Event Handlers let you react to user input in your application. In Dioxus, event handlers accept a closure that is called when the event occurs:

use dioxus::prelude::*;

fn App() -> Element {
    rsx! {
        button {
            // The `onclick` event accepts a closure with the signature `fn(Event)`
            onclick: |event_data| println!("clicked! I got the event data: {event_data:?}"),
            "Click me"
        }
    }
}

§Event Lifetimes

Events take a closure with the 'static lifetime. This means that the closure can only access data that either exists for the entire lifetime of the application, or data that you move into the closure.

State in dioxus is copy which makes it very easy to move into 'static closures like event handlers:

let mut count = use_signal(|| 0);

rsx! {
    button {
        // Since we added the `move` keyword, the closure will move the `count` signal into the closure
        onclick: move |_| {
            // This will panic because the `count` signal is not in scope
            count.set(count() + 1);
        },
        "Click me"
    }
};

If you need to access data that is not Copy, you may need to clone the data before you move it into the closure:

// String is not `Copy`
let string = "hello world".to_string();

rsx! {
    button {
        // The string only has one owner. We could move it into this closure, but since we want to use the string in other closures later, we will clone it instead
        onclick: {
            // Clone the string in a new block
            let string = string.clone();
            // Then move the cloned string into the closure
            move |_| println!("{}", string)
        },
        "Print hello world"
    }
    button {
        // We don't use the string after this closure, so we can just move it into the closure directly
        onclick: move |_| println!("{}", string),
        "Print hello world again"
    }
};

§Async Event Handlers

In addition to closures that return nothing, you can also use async closures to handle events. If you return an async block from an event handler, dioxus will automatically spawn it:

use dioxus::prelude::*;

fn App() -> Element {
    rsx! {
        button {
            // The `onclick` event can also accept a closure that returns an async block
            onclick: move |_| async move {
                tokio::time::sleep(std::time::Duration::from_secs(1)).await;
                println!("You clicked the button one second ago!");
            },
            "Click me"
        }
    }
}

§Compiler errors you may run into while using event handlers

function requires argument type to outlive `'static`

Event handler in Dioxus need only access data that can last for the entire lifetime of the application. That generally means data that is moved into the closure. If you get this error, you may have forgotten to add move to your closure.

Broken component:

// We return an Element which can last as long as the component is on the screen
fn App() -> Element {
    // Signals are `Copy` which makes them very easy to move into `'static` closures like event handlers
    let state = use_signal(|| "hello world".to_string());

    rsx! {
        button {
            // ❌ Without `move`, rust will try to borrow the `state` signal which fails because the state signal is dropped at the end of the function
            onclick: |_| {
                println!("You clicked the button! The state is: {state}");
            },
            "Click me"
        }
    }
    // The state signal is dropped here, but the event handler still needs to access it
}

Fixed component:

fn App() -> Element {
    let state = use_signal(|| "hello world".to_string());

    rsx! {
        button {
            // ✅ The `move` keyword tells rust it can move the `state` signal into the closure. Since the closure owns the signal state, it can read it even after the function returns
            onclick: move |_| {
                println!("You clicked the button! The state is: {state}");
            },
            "Click me"
        }
    }
}
use of moved value: `your_value` value used here after move

Data in rust has a single owner. If you run into this error, you have likely tried to move data that isn’t Copy into two different closures. You can fix this issue by making your data Copy or calling clone on it before you move it into the closure.

Broken component:

// `MyComponent` accepts a string which cannot be copied implicitly
#[component]
fn MyComponent(string: String) -> Element {
    rsx! {
        button {
            // ❌ We are moving the string into the onclick handler which means we can't access it elsewhere
            onclick: move |_| {
                println!("{string}");
            },
            "Print hello world"
        }
        button {
            // ❌ Since we already moved the string, we can't move it into the onclick handler again. This will cause a compiler error
            onclick: move |_| {
                println!("{string}");
            },
            "Print hello world again"
        }
    }
}

You can fix this issue by either:

  • Making your data Copy with ReadOnlySignal:
// `MyComponent` accepts `ReadOnlySignal<String>` which implements `Copy`
#[component]
fn MyComponent(string: ReadOnlySignal<String>) -> Element {
    rsx! {
        button {
            // ✅ Because the `string` signal is `Copy`, we can copy it into the closure while still having access to it elsewhere
            onclick: move |_| println!("{}", string),
            "Print hello world"
        }
        button {
            // ✅ Since `string` is `Copy`, we can move it into the onclick handler again
            onclick: move |_| println!("{}", string),
            "Print hello world again"
        }
    }
}
  • Calling clone on your data before you move it into the closure:
// `MyComponent` accepts a string which doesn't implement `Copy`
#[component]
fn MyComponent(string: String) -> Element {
    rsx! {
        button {
            // ✅ The string only has one owner. We could move it into this closure, but since we want to use the string in other closures later, we will clone it instead
            onclick: {
                // Clone the string in a new block
                let string = string.clone();
                // Then move the cloned string into the closure
                move |_| println!("{}", string)
            },
            "Print hello world"
        }
        button {
            // ✅ We don't use the string after this closure, so we can just move it into the closure directly
            onclick: move |_| println!("{}", string),
            "Print hello world again"
        }
    }
}