knowledge/technology/dev/programming/frameworks/Dioxus.md
JMARyA 4d96dd8987
Some checks are pending
ci/woodpecker/push/validate_schema Pipeline is pending
add dioxus
2025-06-13 10:10:50 +02:00

4.7 KiB

obj website repo
concept https://dioxuslabs.com https://github.com/dioxuslabs/dioxus

Dioxus

Dioxus is a modern, ergonomic, and high-performance Rust framework for building user interfaces using a Virtual DOM (like React). It supports Web, Desktop, TUI, and Mobile targets using a unified component model.

Application

A dioxus app is just a normal rust application. To get started depend on dioxus and start with this main.rs:

use dioxus::prelude::*;

fn main() {
    dioxus::launch(App);
}

#[component]
pub fn App() -> Element {
    rsx! {
        p { "Hello World!" }
    }
}

Components (RSX)

Dioxus components are Rust functions that return Element and use the rsx! macro (similar to JSX). The UI is made with HTML and CSS.

use dioxus::prelude::*;

#[component]
fn App() -> Element {
    rsx! {
        div {
            h1 { "Hello, Dioxus!" }
        }
    }
}

You can define your own components and take values (Props):


#[component]
fn MyComp(value: String, myevent: EventHandler<MouseEvent>, children: Element) -> Element {
    rsx! {
        button {
            onclick: myevent,
            title: value,
            {children}
        }
    }
}

// Usage
#[component]
fn App() -> Element {
    rsx! {
        MyComp {
            // Event Handler
            onclick: move |_| { println!("Clicked"); },
            // Value
            title: "my_title",
            // children
            p {
                "Hello World"
            }
        }
    }
}

Event Handler

Event handling is done inline using closures:

rsx!(
    button {
        onclick: move |_| println!("Button clicked"),
        "Click me"
    }
)

Each event handler receives an event struct (e.g., MouseEvent, FormEvent).

Hooks

Dioxus has a powerful hook system that allows you to manage state, side effects, and asynchronous operations in your components. With these hooks the UI gets automatically reloaded when needed.

Warning

: Always call the hooks in the same order or they will not work correctly. This means no hooks in loops or conditions.

use_signal

Creates a reactive value that can be read and updated. When the value changes, the component re-renders.

let count = use_signal(|| 0);
rsx! {
    button { onclick: move |_| count.set(count() + 1), "Increment" }
    p { "Value is {count}" }
}

use_memo

Computes a derived value that only re-evaluates when its dependencies change.

let doubled = use_memo(|| count() * 2);

use_effect

Runs a side effect after the component renders. Useful for operations which should run beside the UI.

use_effect(|| {
    // Side effect code here
});

use_resource

Manages an asynchronous resource, such as data fetched from an API.

let resource = use_resource(|| fetch_data());

use_drop

Registers a callback to be run before the component is removed. Useful for cleaning up side effects.

use_drop(|| {
    // Cleanup code here
});

Assets

To include assets (like CSS) in our app, you can use the asset!() macro. This macro ensures the asset will be included in the final app bundle.

static MY_CSS: Asset = asset!("/assets/main.css");

fn App() -> Element {
    rsx! {
        document::Stylesheet { href: MY_CSS }
    }
}

Routing

You can have different routes in your app using dioxus router. To use the router enable the router feature in the dioxus crate.

Define the routes:

// All of our routes will be a variant of this Route enum
#[derive(Routable, PartialEq, Clone)]
enum Route {
    // if the current location is "/home", render the Home component
    #[route("/home")]
    Home {},
    // if the current location is "/blog", render the Blog component
    #[route("/blog")]
    Blog {},
}

fn Home() -> Element {
    todo!()
}

fn Blog() -> Element {
    todo!()
}

To use the router and actually render the routes, add it to your main App component:

fn App() -> Element {
    rsx! {
        document::Stylesheet { href: asset!("/assets/main.css") }

        // Renders the current route
        Router::<Route> {}
    }
}

To move between routes you can either use a Link element or the navigator:

// Link Element
rsx! {
    Link { to: Route::Home {}, "Go home!" }
}

// Navigator
rsx! {
    button {
        onclick: move |_| {
            let nav = navigator();
            
            // push
            nav.push(Route::Blog {});
            
            // replace
            nav.replace(Route::Home {});
            
            // go back
            nav.go_back();
            
            // go forward
            nav.go_forward();
        },
        "Go somewhere"
    }
}