Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Roblox/roact/llms.txt

Use this file to discover all available pages before exploring further.

Elements are the foundational building blocks of every Roact UI. Before any component logic runs or any Roblox Instances appear on screen, you describe what you want using elements — plain, lightweight Lua tables that capture a snapshot of your UI at a single point in time.

What Are Elements?

An element is an immutable description of what a piece of UI should look like right now. You cannot modify an element after creating it, but creating new elements is extremely cheap, so Roact encourages you to produce them freely and often. When you need the UI to change, you simply describe the new desired state and hand it back to Roact. Elements are created with Roact.createElement. Host elements use a Roblox class name string — such as "Frame" or "TextLabel" — as their first argument. Roact maps these directly to the corresponding Roblox Instance types.
local myElement = Roact.createElement("Frame", {
    Size = UDim2.new(0, 50, 0, 50)
})

createElement Signature

Roact.createElement(component, props, children)
ArgumentTypeDescription
componentstring or componentA Roblox class name string ("Frame") or a Roact component.
propstable | nilProperties to apply. For host components these become Instance properties.
childrentable | nilA dictionary of named child elements.

Props

The second argument is a table of props. For host components (string class names), every key-value pair in this table is applied directly as a property on the resulting Roblox Instance.
local label = Roact.createElement("TextLabel", {
    Text = "Hello, Roact!",
    Size = UDim2.new(1, 0, 1, 0),
    BackgroundTransparency = 1,
})

Children

The third argument is a dictionary of named child elements. Each key is an arbitrary name used by Roact to track the child across updates; each value is another element produced by createElement.
local myElement = Roact.createElement("Frame", {
    Size = UDim2.new(0, 50, 0, 50)
}, {
    SomeChild = Roact.createElement("TextLabel", {
        Text = "Hello, Roact!"
    })
})
Children can themselves have children, allowing you to build arbitrarily deep UI trees from plain Lua table literals.

Mounting, Updating, and Unmounting

Creating an element alone doesn’t produce any Roblox Instances. You must mount the element to turn it into real UI. The three lifecycle functions below manage the full lifespan of a Roact tree.
1

Mount the element

Call Roact.mount to create a live UI tree from an element. Pass the element, a parent Instance, and an optional name for the root object. It returns a RoactTree handle you must hold on to.
local handle = Roact.mount(myElement, game.Workspace, "MyUI")
Mounting is the process of constructing component instances and their associated Roblox Instances for the first time.
2

Update the tree

To change the UI, create a new element describing the desired state and pass it to Roact.update along with the existing handle. Roact reconciles the old tree against the new one, making only the minimal set of changes needed.
local myNewElement = Roact.createElement("Frame", {
    Size = UDim2.new(0, 100, 0, 50)
}, {
    SomeChild = Roact.createElement("TextLabel", {
        Text = "Hello, again, Roact!"
    })
})

handle = Roact.update(handle, myNewElement)
As of Roact v1.0, Roact.update returns the same tree object that was passed in. The handle remains valid. Reassigning it (as shown above) is conventional and safe, but the original variable continues to point to the same tree.
3

Unmount the tree

When you are finished with a piece of UI, call Roact.unmount. This destroys all associated Roblox Instances and cleans up all internal Roact state for that tree.
Roact.unmount(handle)
Do not use a handle after passing it to Roact.unmount. The handle is invalidated immediately, and any further calls using it will result in errors.

Reconciliation

Reconciliation is Roact’s process of comparing an existing UI tree to a new element tree and efficiently updating only the Instances that have changed. Rather than tearing down and recreating everything, Roact computes the difference (diff) between the old and new virtual trees and applies targeted property changes to the real Roblox Instances. This is what makes the Roact.update call cheap even for large UI trees — unchanged subtrees are left completely untouched.

Full Example: Incrementing Counter

The example below puts everything together. A clock function returns a fresh element tree each call, and Roact.update reconciles the tree every second. This is a complete LocalScript that can be placed in StarterPlayerScripts with Roact installed in ReplicatedStorage.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local Roact = require(ReplicatedStorage.Roact)

-- Create a function that creates the elements for our UI.
-- Later, we'll use components, which are the best way to organize UI in Roact.
local function clock(currentTime)
    return Roact.createElement("ScreenGui", {}, {
        TimeLabel = Roact.createElement("TextLabel", {
            Size = UDim2.new(1, 0, 1, 0),
            Text = "Time Elapsed: " .. currentTime
        })
    })
end

local PlayerGui = Players.LocalPlayer.PlayerGui

-- Mount the initial UI.
local currentTime = 0
local handle = Roact.mount(clock(currentTime), PlayerGui, "Clock UI")

-- Every second, create new elements and reconcile the tree.
while true do
    wait(1)

    currentTime = currentTime + 1
    handle = Roact.update(handle, clock(currentTime))
end
In the next section you will learn about components, which let you encapsulate this element-creation logic into reusable, self-contained pieces.

Build docs developers (and LLMs) love