diff --git a/technology/dev/programming/frameworks/Dioxus.md b/technology/dev/programming/frameworks/Dioxus.md new file mode 100644 index 0000000..9f77faf --- /dev/null +++ b/technology/dev/programming/frameworks/Dioxus.md @@ -0,0 +1,229 @@ +--- +obj: concept +website: https://dioxuslabs.com +repo: 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`: + +```rust +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. + +```rust +use dioxus::prelude::*; + +#[component] +fn App() -> Element { + rsx! { + div { + h1 { "Hello, Dioxus!" } + } + } +} +``` + +You can define your own components and take values (Props): + +```rust + +#[component] +fn MyComp(value: String, myevent: EventHandler, 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: + +```rust +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. + +```rust +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. + +```rust +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. + +```rust +use_effect(|| { + // Side effect code here +}); +``` + +### `use_resource` + +Manages an asynchronous resource, such as data fetched from an API. + +```rust +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. + +```rust +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. + +```rust +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**: + +```rust +// 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: +```rust +fn App() -> Element { + rsx! { + document::Stylesheet { href: asset!("/assets/main.css") } + + // Renders the current route + Router:: {} + } +} +``` + +To move between routes you can either use a `Link` element or the `navigator`: + +```rust +// 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" + } +} +```