Skip to main content

Overview

The Element type represents a renderable piece of UI in Dioxus. It’s the return type of all components and is built from VNodes (virtual nodes) that describe the structure of the DOM.

Element Type

Element is a type alias for Result<VNode, RenderError>. Components return an Element, which can either be:
  • Ok(VNode) - A successfully rendered node
  • Err(RenderError) - An error that propagates to the nearest error boundary
pub type Element = Result<VNode, RenderError>;

Creating Elements

use dioxus::prelude::*;

#[component]
fn MyComponent() -> Element {
    rsx! {
        div { "Hello, world!" }
    }
}

// Returning an empty element
fn EmptyComponent() -> Element {
    VNode::empty()
}

// Returning an error
fn ErrorComponent() -> Element {
    Err(RenderError::from(anyhow::anyhow!("Something went wrong")))
}

VNode

VNode is the core virtual node type that represents a template with dynamic content.

Structure

pub struct VNode {
    vnode: Rc<VNodeInner>,
    mount: Cell<MountId>,
}

pub struct VNodeInner {
    pub key: Option<String>,
    pub template: Template,
    pub dynamic_nodes: Box<[DynamicNode]>,
    pub dynamic_attrs: Box<[Box<[Attribute]>]>,
}

Methods

VNode::empty()

Creates an element with no nodes that will be skipped during diffing.
fn render() -> Element {
    if condition {
        rsx! { div { "Content" } }
    } else {
        VNode::empty()
    }
}

VNode::placeholder()

Creates a template with a single placeholder node.
let placeholder = VNode::placeholder();

VNode::new()

Creates a new VNode with the specified template and dynamic content.
pub fn new(
    key: Option<String>,
    template: Template,
    dynamic_nodes: Box<[DynamicNode]>,
    dynamic_attrs: Box<[Box<[Attribute]>]>,
) -> Self

Template

The Template struct describes the static structure of a UI tree. This is the core optimization in Dioxus - most UI is static and can be represented at compile time.

Structure

pub struct Template {
    pub roots: &'static [TemplateNode],
    pub node_paths: &'static [&'static [u8]],
    pub attr_paths: &'static [&'static [u8]],
}

Fields

roots
&'static [TemplateNode]
The list of root template nodes. Unlike React, Dioxus supports multiple roots.
node_paths
&'static [&'static [u8]]
Paths to each dynamic node relative to the template root.
attr_paths
&'static [&'static [u8]]
Paths to each dynamic attribute relative to the template root.

TemplateNode

Represents a statically known node in the template.
pub enum TemplateNode {
    Element {
        tag: &'static str,
        namespace: Option<&'static str>,
        attrs: &'static [TemplateAttribute],
        children: &'static [TemplateNode],
    },
    Text {
        text: &'static str,
    },
    Dynamic {
        id: usize,
    },
}

Variants

Element
struct
A static HTML element with tag name, namespace, attributes, and children.
TemplateNode::Element {
    tag: "div",
    namespace: None,
    attrs: &[],
    children: &[],
}
Text
struct
A static text node.
TemplateNode::Text {
    text: "Hello, world!",
}
Dynamic
struct
A placeholder for a dynamic node. The id indexes into the VNode’s dynamic_nodes array.
TemplateNode::Dynamic { id: 0 }

DynamicNode

Represents runtime-determined nodes in the template.
pub enum DynamicNode {
    Component(VComponent),
    Text(VText),
    Placeholder(VPlaceholder),
    Fragment(Vec<VNode>),
}

Variants

Component
VComponent
A child component with props and render function.
Text
VText
A dynamically generated text node.
let count = 42;
rsx! { "{count}" } // Creates DynamicNode::Text
Placeholder
VPlaceholder
A placeholder used by suspense and fragments that render nothing.
Fragment
Vec<VNode>
A list of VNodes created by conditional rendering or iterators.
rsx! {
    for item in items {
        div { "{item}" }
    }
}

VText

A text node with dynamic content.
pub struct VText {
    pub value: String,
}

Methods

VText::new()

Creates a new text node.
let text = VText::new("Hello");
let text_from_num = VText::new(42.to_string());

Example Usage

use dioxus::prelude::*;

#[component]
fn App() -> Element {
    let mut count = use_signal(|| 0);
    
    rsx! {
        div {
            h1 { "Counter: {count}" }
            button {
                onclick: move |_| count += 1,
                "Increment"
            }
            // Conditional rendering
            if count() > 5 {
                p { "Count is greater than 5!" }
            }
            // List rendering
            ul {
                for i in 0..count() {
                    li { key: "{i}", "Item {i}" }
                }
            }
        }
    }
}

See Also

Build docs developers (and LLMs) love