DEV Community

Alex Spinov
Alex Spinov

Posted on

Dioxus Has a Free API: Write React-Style UIs in Rust That Run Everywhere — Web, Desktop, Mobile

A mobile developer spent six months building the same feature three times: once in Swift for iOS, once in Kotlin for Android, and once in React for the web version. The logic was identical. Only the UI framework was different. He kept thinking there had to be a better abstraction.

Dioxus is that abstraction. It is a cross-platform UI framework written in Rust that uses a React-inspired component model — but compiles to native desktop, mobile, web (via WASM), and server-side rendering from the same codebase. Write once, ship everywhere, without sacrificing performance.

What Dioxus Actually Does

Dioxus is an open-source Rust UI library inspired by React's component model but built on top of a virtual DOM implemented in Rust. Components look and feel like React functional components. Props, state hooks, event handlers, and lifecycle effects all map to familiar concepts — but the underlying runtime is Rust, not JavaScript.

The framework targets multiple renderers through a single API:

  • Web: Compiles to WASM, runs in the browser
  • Desktop: Uses system webview for native apps
  • Mobile: iOS and Android via native webview bridge
  • SSR: Server-side rendering for fast initial page loads
  • TUI: Terminal UI rendering (yes, terminal apps too)

Dioxus also has a first-class CLI (dx) that hot-reloads RSX (their JSX equivalent) without full recompiles, making the development experience fast despite Rust's compilation times.

Quick Start: First Component in 5 Minutes

Install the toolchain:

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install Dioxus CLI
cargo install dioxus-cli

# Add WASM target for web
rustup target add wasm32-unknown-unknown
Enter fullscreen mode Exit fullscreen mode

Create and run a web project:

dx new my-dioxus-app
cd my-dioxus-app
dx serve --platform web
Enter fullscreen mode Exit fullscreen mode

A complete Todo app that works on web, desktop, and mobile without changing a single line:

use dioxus::prelude::*;

#[derive(Clone, PartialEq)]
struct TodoItem {
    id: usize,
    text: String,
    done: bool,
}

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

#[component]
fn App() -> Element {
    let mut todos = use_signal(|| vec![
        TodoItem { id: 1, text: "Learn Dioxus".to_string(), done: false },
        TodoItem { id: 2, text: "Build something great".to_string(), done: false },
    ]);
    let mut new_todo = use_signal(|| String::new());

    rsx! {
        div { class: "app",
            h1 { "My Todo List" }
            input {
                value: "{new_todo}",
                placeholder: "Add a new todo...",
                oninput: move |e| new_todo.set(e.value()),
            }
            ul {
                for todo in todos.iter() {
                    li { "{todo.text}" }
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3 Practical Use Cases

1. Desktop App with Native File System Access

Dioxus Desktop runs as a native application with full OS access:

use dioxus::prelude::*;
use std::fs;

#[component]
fn FileReader() -> Element {
    let mut content = use_signal(|| String::from("No file loaded"));

    rsx! {
        div {
            button {
                onclick: move |_| {
                    if let Ok(data) = fs::read_to_string("/etc/hostname") {
                        content.set(data);
                    }
                },
                "Read File"
            }
            pre { "{content}" }
        }
    }
}

fn main() {
    dioxus::LaunchBuilder::desktop()
        .with_cfg(dioxus::desktop::Config::new()
            .with_window(dioxus::desktop::WindowBuilder::new()
                .with_title("File Reader")))
        .launch(FileReader);
}
Enter fullscreen mode Exit fullscreen mode

2. API-Driven Web App with Async Data Fetching

Fetch data from a REST API and display it reactively:

use dioxus::prelude::*;
use serde::Deserialize;

#[derive(Deserialize, Clone, PartialEq)]
struct Post {
    id: u32,
    title: String,
    body: String,
}

#[server]
async fn fetch_posts() -> Result<Vec<Post>, ServerFnError> {
    let posts: Vec<Post> = reqwest::get("https://jsonplaceholder.typicode.com/posts")
        .await?
        .json()
        .await?;
    Ok(posts[..5].to_vec())
}

#[component]
fn PostList() -> Element {
    let posts = use_resource(fetch_posts);

    rsx! {
        match posts.read_unchecked().as_ref() {
            None => rsx! { p { "Loading..." } },
            Some(Ok(posts)) => rsx! {
                ul {
                    for post in posts.iter() {
                        li { key: "{post.id}", h3 { "{post.title}" } }
                    }
                }
            },
            Some(Err(e)) => rsx! { p { "Error: {e}" } },
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Shared Components Across All Platforms

The same component tree renders on every platform:

// This component works on web, desktop, AND mobile unchanged
#[component]
fn UserCard(name: String, avatar_url: String, bio: String) -> Element {
    rsx! {
        div { class: "card",
            img { src: "{avatar_url}", alt: "{name}'s avatar" }
            h2 { "{name}" }
            p { "{bio}" }
            button {
                onclick: move |_| {
                    // Platform detection at compile time
                    #[cfg(target_arch = "wasm32")]
                    web_sys::window().unwrap().alert_with_message("Follow clicked!").ok();
                    #[cfg(not(target_arch = "wasm32"))]
                    println!("Follow clicked for {name}");
                },
                "Follow"
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Why This Matters

Cross-platform UI development has been the white whale of software engineering for decades. Electron apps are bloated. React Native apps hit performance walls. Flutter requires learning Dart. Dioxus offers a fundamentally different approach: use Rust's performance and memory safety as the foundation, and compile to whatever target you need.

The framework is actively developed at dioxuslabs.com with 22,000+ GitHub stars and a growing ecosystem. The component model is stable enough for production use.

If you are building an app that needs to run on multiple platforms without duplicating your codebase — Dioxus is the most promising path forward that does not require hiring three different teams.


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)