You need an app that runs on web, desktop, and mobile. React Native covers web and mobile but desktop is Electron — 200MB of Chromium per app. Flutter covers all three but you're learning Dart. What if you could write one Rust codebase and compile to all platforms natively? Dioxus does exactly that.
What Dioxus Actually Does
Dioxus is a Rust UI framework inspired by React. You write components with a familiar JSX-like syntax (using Rust macros), manage state with hooks, and handle events — all in Rust. The same code compiles to WebAssembly (browser), native desktop (no Electron), mobile (iOS/Android), and terminal UI.
Dioxus uses a virtual DOM like React, but the renderer is pluggable. For web, it renders to the real DOM via WASM. For desktop, it uses a native webview (5MB, not 200MB Electron). For mobile, it targets native views. For TUI, it renders to the terminal.
Dioxus includes a CLI tool (dx) for hot-reloading, asset management, and cross-platform builds. Open-source under MIT/Apache 2.0.
Quick Start
cargo install dioxus-cli
dx new my-app
cd my-app
dx serve # Launches with hot-reload
A basic component:
use dioxus::prelude::*;
fn main() {
launch(App);
}
#[component]
fn App() -> Element {
let mut count = use_signal(|| 0);
rsx! {
div {
h1 { "Counter: {count}" }
button { onclick: move |_| count += 1, "Increment" }
button { onclick: move |_| count -= 1, "Decrement" }
}
}
}
Build for different platforms:
dx serve --platform web # Browser (WASM)
dx serve --platform desktop # Native desktop window
dx serve --platform mobile # iOS/Android
3 Practical Use Cases
1. Data Fetching with Suspense
#[component]
fn UserProfile(id: i32) -> Element {
let user = use_resource(move || async move {
reqwest::get(format!("https://api.example.com/users/{id}"))
.await?.json::<User>().await
});
match &*user.read() {
Some(Ok(user)) => rsx! {
div { class: "profile",
h2 { "{user.name}" }
p { "{user.email}" }
img { src: "{user.avatar_url}" }
}
},
Some(Err(e)) => rsx! { p { "Error: {e}" } },
None => rsx! { p { "Loading..." } }
}
}
2. Native Desktop App with System Tray
use dioxus::prelude::*;
use dioxus_desktop::{Config, WindowBuilder};
fn main() {
let cfg = Config::new()
.with_window(
WindowBuilder::new()
.with_title("My Rust App")
.with_inner_size(dioxus_desktop::LogicalSize::new(800, 600))
);
LaunchBuilder::desktop().with_cfg(cfg).launch(App);
}
5MB binary vs 200MB Electron. Native performance. System-level access.
3. Shared Components Across Platforms
// This component works on web, desktop, mobile, and TUI
#[component]
fn TodoList() -> Element {
let mut todos = use_signal(Vec::<String>::new);
let mut input = use_signal(String::new);
rsx! {
input {
value: "{input}",
oninput: move |e| input.set(e.value())
}
button {
onclick: move |_| {
todos.push(input().clone());
input.set(String::new());
},
"Add"
}
ul {
for (i, todo) in todos().iter().enumerate() {
li { key: "{i}", "{todo}" }
}
}
}
}
Write once, run on every platform — with Rust's type safety.
Why This Matters
Dioxus bridges the gap between Rust's systems programming power and modern UI development. If you're already writing Rust, Dioxus means no context switching to JavaScript/TypeScript for your frontend. The cross-platform story is compelling: one codebase, native performance on every platform, and a familiar React-like API.
For desktop apps especially, Dioxus is a game-changer: 5MB native apps instead of 200MB Electron bundles, with full system access and Rust's memory safety guarantees.
Need custom data extraction or web scraping solutions? I build production-grade scrapers and data pipelines. Check out my Apify actors or email me at spinov001@gmail.com for custom projects.
Follow me for more free API discoveries every week!
Top comments (0)