Skip to main content
Components are the fundamental building blocks of Dioxus applications. They are reusable, composable functions that return UI elements.

Component Basics

A component is a function that returns an Element. The simplest component takes no arguments:
use dioxus::prelude::*;

fn App() -> Element {
    rsx! {
        div { "Hello, world!" }
    }
}

The Element Type

The Element type is defined as:
type Element = std::result::Result<VNode, RenderError>;
It represents a possibly-none VNode created by calling render on a component. An errored Element will propagate the error to the nearest error boundary.

The #[component] Macro

The #[component] macro is the recommended way to create components with props. It automatically generates a props struct and handles component registration.

Basic Usage

use dioxus::prelude::*;

#[component]
fn Greeting(name: String) -> Element {
    rsx! {
        div { "Hello, {name}!" }
    }
}
This is equivalent to manually defining:
#[derive(Props, PartialEq, Clone)]
struct GreetingProps {
    name: String,
}

fn Greeting(props: GreetingProps) -> Element {
    rsx! {
        div { "Hello, {props.name}!" }
    }
}

Component Naming

Components must use:
  • PascalCase (recommended): MyComponent, UserProfile
  • snake_case with underscore: my_component, user_profile
You can disable the case check with #[component(no_case_check)] if needed.

Props and Parameters

Components can accept parameters which become props:
#[component]
fn UserCard(
    name: String,
    age: i32,
    #[props(default = "user.png".to_string())]
    avatar: String,
) -> Element {
    rsx! {
        div {
            img { src: "{avatar}" }
            h2 { "{name}" }
            p { "Age: {age}" }
        }
    }
}

Using Components

Call components in rsx! like HTML elements:
rsx! {
    UserCard {
        name: "Alice",
        age: 30,
    }
}

Children

Components can accept children by including a children: Element parameter:
#[component]
fn Card(children: Element) -> Element {
    rsx! {
        div { class: "card",
            {children}
        }
    }
}

// Usage
rsx! {
    Card {
        h1 { "Title" }
        p { "Content" }
    }
}

Component Function Trait

Components must implement the ComponentFunction trait. This is automatically done for:
  • Functions with signature fn() -> Element
  • Functions with signature fn(Props) -> Element where Props implements Properties
  • Functions marked with #[component]
pub trait ComponentFunction<Props, Marker = ()>: Clone + 'static {
    fn rebuild(&self, props: Props) -> Element;
}

Component Lifecycle

Components in Dioxus:
  1. First render: Component function is called with props
  2. Re-render: When props change or state updates, component re-runs
  3. Cleanup: When component is unmounted, hooks clean up automatically
Components are memoized by default - they only re-render when their props change (using PartialEq) or when subscribed signals/state update.

Best Practices

Keep Components Small

Break down complex UIs into smaller, focused components for better reusability and testing.

Use PascalCase

Follow Rust conventions and use PascalCase for component names to distinguish them from HTML elements.

Props Should Be PartialEq

Props must implement PartialEq for memoization - this prevents unnecessary re-renders.

Return Element

Always return Element from components. Use rsx! macro to construct UI.

Example: Complete Component

use dioxus::prelude::*;

#[component]
fn TodoItem(
    text: String,
    completed: bool,
    on_toggle: EventHandler<()>,
) -> Element {
    rsx! {
        li {
            class: if completed { "completed" } else { "" },
            input {
                r#type: "checkbox",
                checked: completed,
                onclick: move |_| on_toggle.call(()),
            }
            span { "{text}" }
        }
    }
}

fn App() -> Element {
    let mut completed = use_signal(|| false);
    
    rsx! {
        TodoItem {
            text: "Learn Dioxus",
            completed: completed(),
            on_toggle: move |_| completed.toggle(),
        }
    }
}

See Also

  • Props - Learn about passing data to components
  • RSX - Understand the RSX macro syntax
  • State - Manage component state

Build docs developers (and LLMs) love