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.

Roact exposes its entire public surface through a single module returned by require(Roact). This page documents every function, component type, and special constant available on that table. All examples assume you have already required Roact and assigned it to a local variable named Roact.

Methods

Roact.createElement

Roact.createElement(component, [props, [children]]) -> RoactElement
Creates a new Roact element representing the given component. Elements are lightweight descriptions of what a Roblox Instance should look like — think of them as blueprints rather than the real thing. Roact uses these descriptions during mounting and reconciliation to create and update actual Roblox Instances. component can be a string (a Roblox host class name such as "Frame"), a function component, or a table produced by Component:extend. The optional children argument is shorthand for placing a Roact.Children key inside props; it should be a dictionary mapping string names to child elements.
Do not modify props or children after passing them to createElement. Roact may read these tables at any time during reconciliation, and mutations will cause unpredictable behavior.
component
string | function | table
required
The component to create an element for. Pass a Roblox class name string for host components, a function for function components, or a class table returned by Component:extend for stateful components.
props
table
A dictionary of properties and special prop-marker keys to apply to this element. Pass nil or omit to use no props.
children
table
A dictionary of name-to-element pairs that become the children of this element. Equivalent to setting props[Roact.Children] directly.
Returns: RoactElement — a lightweight, immutable description of the desired UI.
-- Host component (string)
local frame = Roact.createElement("Frame", {
    Size = UDim2.new(1, 0, 1, 0),
    BackgroundColor3 = Color3.fromRGB(30, 30, 30),
}, {
    Label = Roact.createElement("TextLabel", {
        Text = "Hello, Roact!",
        Size = UDim2.new(1, 0, 0, 40),
    }),
})

-- Function component
local function Greeting(props)
    return Roact.createElement("TextLabel", { Text = props.name })
end

local greeting = Roact.createElement(Greeting, { name = "World" })

Roact.createFragment

Roact.createFragment(elements) -> RoactFragment
Added in Roact 1.0.0.
Creates a new Roact fragment from a table of elements. Fragments let you group multiple sibling elements and return them together from a component’s render method without needing a wrapping container like a Frame. They are transparent to the Roblox Instance hierarchy — children of a fragment are placed directly into the fragment’s parent.
Do not modify the elements table after passing it to createFragment. Like createElement, Roact may inspect this table at any time.
elements
table
required
A dictionary of name-to-element pairs to include in the fragment. The keys are used as child names within the parent’s children.
Returns: RoactFragment — an element-like value that renders its children without a wrapping Instance.
local function TwoLabels(props)
    return Roact.createFragment({
        First = Roact.createElement("TextLabel", {
            Text = "First",
            Position = UDim2.new(0, 0, 0, 0),
        }),
        Second = Roact.createElement("TextLabel", {
            Text = "Second",
            Position = UDim2.new(0, 0, 0, 30),
        }),
    })
end

Roact.mount

Roact.mount(element, [parent, [key]]) -> RoactTree
Roact.mount is also available under the deprecated alias Roact.reify. The alias will be removed in a future release.
Takes a Roact element and creates the corresponding Roblox Instances, optionally parenting the root Instance to parent and naming it with key. This is the entry point for putting a Roact component tree into the game world. The returned RoactTree is an opaque handle that you pass to Roact.update and Roact.unmount.
element
RoactElement
required
The root element to mount. Must be a value returned by Roact.createElement or Roact.createFragment.
parent
Instance
The Roblox Instance to parent the root Instance into. Omit to leave the tree unparented.
key
string
The Name property to assign to the root Instance. Omit to use Roact’s default naming.
Returns: RoactTree — an opaque handle representing the live component tree.
local element = Roact.createElement("ScreenGui", {}, {
    Label = Roact.createElement("TextLabel", { Text = "Mounted!" }),
})

local tree = Roact.mount(element, Players.LocalPlayer.PlayerGui, "MyUI")

Roact.update

Roact.update(tree, element) -> RoactTree
Roact.update is also available under the deprecated alias Roact.reconcile. The alias will be removed in a future release.
Reconciles an existing mounted tree against a new element, efficiently applying only the differences. This is useful for integrating a Roact UI into a non-Roact application where you control the top-level props from outside. As of Roact 1.0, the returned RoactTree is the same object that was passed in.
tree
RoactTree
required
The handle returned by a previous call to Roact.mount.
element
RoactElement
required
The new element to reconcile the tree against.
Returns: RoactTree — the same handle that was passed in, now updated.
local tree = Roact.mount(Roact.createElement("TextLabel", { Text = "Before" }), parent)

-- Later, update the tree with new props:
tree = Roact.update(tree, Roact.createElement("TextLabel", { Text = "After" }))

Roact.unmount

Roact.unmount(tree) -> void
Roact.unmount is also available under the deprecated alias Roact.teardown. The alias will be removed in a future release.
Destroys the given RoactTree and all its descendants, firing willUnmount on every stateful component in the tree. The associated Roblox Instances are also destroyed. After calling unmount, the tree handle is no longer valid.
tree
RoactTree
required
The handle returned by Roact.mount. Must not be a Roblox Instance.
local tree = Roact.mount(element, parent, "MyUI")

-- When done with the UI:
Roact.unmount(tree)

Roact.oneChild

Roact.oneChild(children) -> RoactElement | nil
A utility that extracts a single child element from a children dictionary. If children is nil or empty, it returns nil. If children contains exactly one child, that child element is returned. If children contains more than one child, an error is thrown — this is intentional, to surface programming errors in components that expect at most one child.
children
table
The self.props[Roact.Children] table, or any dictionary of named elements.
Returns: RoactElement | nil — the single child element, or nil if there are no children.
local function SingleChildWrapper(props)
    local child = Roact.oneChild(props[Roact.Children])

    return Roact.createElement("Frame", {
        Size = UDim2.new(1, 0, 1, 0),
    }, {
        Child = child,
    })
end

Roact.createBinding

Roact.createBinding(initialValue) -> Binding, updateFunction
Added in Roact 1.0.0.
Creates a Binding — a special reactive value that can be passed directly as a prop to host components. When the binding’s value is updated, Roact updates only the specific Instance properties that depend on it, without triggering a full re-render of the component tree. This makes bindings ideal for frequently-changing values such as animation progress or cursor position. The first return value is the Binding object. The second is an updater function; call it with a new value to push that value through all subscribers of the binding.
initialValue
any
required
The starting value of the binding. Can be any Lua value.
Returns: Binding, (newValue: any) -> void — the binding object and its updater function.

Binding:getValue

binding:getValue() -> value
Returns the current internal value of the binding.
Calling getValue() inside render and using the result directly as a prop value will not subscribe the component to future updates. Always pass the binding object itself as the prop value to ensure Roact can track changes.

Binding:map

binding:map(mappingFunction) -> Binding
Returns a new derived binding whose value is computed by applying mappingFunction to the upstream binding’s value. The derived binding updates automatically whenever the upstream binding updates.
local MyComponent = Roact.Component:extend("MyComponent")

function MyComponent:init()
    self.progress, self.setProgress = Roact.createBinding(0)
end

function MyComponent:render()
    return Roact.createElement("Frame", {
        -- Pass the binding directly so Roact subscribes to updates
        Size = self.progress:map(function(value)
            return UDim2.new(value, 0, 1, 0)
        end),
    })
end

function MyComponent:didMount()
    -- Update the binding; only the Size property is patched, no re-render
    self.setProgress(0.75)
end

Roact.joinBindings

Roact.joinBindings(bindings) -> Binding
Added in Roact 1.1.0.
Combines multiple bindings into a single binding whose value is a table with the same keys as the input. Whenever any upstream binding updates, the joined binding fires with a fresh snapshot of all values. Joined bindings cannot be updated directly; use Binding:map on the result to transform the combined value.
bindings
table
required
A dictionary (or array) of Binding values to combine. All values must be bindings.
Returns: Binding — a single binding whose value mirrors the current values of all inputs.
local aSize, setASize = Roact.createBinding(Vector2.new())
local bSize, setBSize = Roact.createBinding(Vector2.new())

local totalSize = Roact.joinBindings({ a = aSize, b = bSize }):map(function(sizes)
    return UDim2.new(0, sizes.a.X + sizes.b.X, 0, sizes.a.Y + sizes.b.Y)
end)

return Roact.createElement("Frame", { Size = totalSize })

Roact.createRef

Roact.createRef() -> Ref
Creates a new ref object for use with the Roact.Ref prop marker. A ref gives you direct access to the underlying Roblox Instance rendered by a host component. Refs are a kind of binding: call ref:getValue() to retrieve the current Instance. Returns: Ref — a ref object with a getValue() method and a deprecated current field.
local MyComponent = Roact.Component:extend("MyComponent")

function MyComponent:init()
    self.frameRef = Roact.createRef()
end

function MyComponent:render()
    return Roact.createElement("Frame", {
        [Roact.Ref] = self.frameRef,
    })
end

function MyComponent:didMount()
    local frame = self.frameRef:getValue()
    print("Frame Instance:", frame)
end

Roact.forwardRef

Roact.forwardRef(render) -> RoactComponent
Added in Roact 1.4.0.
Creates a component that forwards a ref passed by its parent down to an underlying host component. This is necessary because refs are stripped from props before they reach a function component; forwardRef is the sanctioned way to pass them through.
render
function
required
A function with the signature function(props, ref) -> RoactElement. props is the component’s props table (with the ref removed), and ref is the forwarded ref that should be assigned to a host element via [Roact.Ref].
Returns: RoactComponent — a component that can be used with Roact.createElement.
local FancyButton = Roact.forwardRef(function(props, ref)
    return Roact.createElement("TextButton", {
        Text = props.label,
        Size = UDim2.new(0, 120, 0, 40),
        [Roact.Ref] = ref,
    })
end)

-- In a parent component:
local buttonRef = Roact.createRef()
local element = Roact.createElement(FancyButton, {
    label = "Click me",
    [Roact.Ref] = buttonRef,
})

Roact.createContext

Roact.createContext(defaultValue) -> RoactContext
Added in Roact 1.3.0.
Creates a new context, returning a table with two components: Provider and Consumer. Context lets you share a value (such as a theme, locale, or data store) through an arbitrary depth of the component tree without threading it through every intermediate component’s props. defaultValue is used when a Consumer has no Provider ancestor. It is the responsibility of the application author to decide whether that situation is valid.
defaultValue
any
required
The fallback value given to any Consumer that is not a descendant of a matching Provider.
Returns: { Provider: Component, Consumer: Component } — the context provider and consumer pair.

Provider props

value
any
required
The value to make available to all descendant Consumer components. When this prop changes, all reachable consumers are re-rendered.
[Roact.Children]
table
Child elements to render underneath the provider.

Consumer props

render
function
required
A function with the signature function(value) -> RoactElement | nil. Called every time the consumer renders, receiving the current context value.
local ThemeContext = Roact.createContext({ primary = Color3.fromRGB(0, 120, 215) })

-- Wrap your tree with a Provider:
local app = Roact.createElement(ThemeContext.Provider, {
    value = { primary = Color3.fromRGB(255, 80, 0) },
}, {
    Main = Roact.createElement(MainScreen),
})

-- Anywhere inside, consume the value:
local function ThemedButton(props)
    return Roact.createElement(ThemeContext.Consumer, {
        render = function(theme)
            return Roact.createElement("TextButton", {
                BackgroundColor3 = theme.primary,
                Text = props.label,
            })
        end,
    })
end

Roact.setGlobalConfig

Roact.setGlobalConfig(configValues) -> void
Configures global Roact behavior. Because this setting applies to the entire Roact instance (all code sharing the same require result), it should be called once at the root of your project before any components are mounted.
setGlobalConfig is global — it affects every consumer of this Roact instance. If your project uses multiple packages that also depend on Roact, changing the config may affect them too. Most options carry a performance cost and should be disabled in production.
Enable typeChecks and propValidation during development to catch mistakes early, then disable them before shipping to production.
configValues
table
required
A dictionary of config key strings to boolean values. Unknown keys will cause an error.
The valid config keys are:
KeyDescription
typeChecksValidates types on Roact’s public API (props, arguments to createElement, etc.)
internalTypeChecksValidates types inside Roact’s internal implementation. Primarily useful when debugging Roact itself.
elementTracingCaptures a stack trace at each createElement call site and attaches it to the element for richer error messages. Also enables getElementTraceback.
propValidationRuns each component’s validateProps static method before every prop update.
-- At the top of your project entry point:
Roact.setGlobalConfig({
    typeChecks = true,
    elementTracing = true,
    propValidation = true,
})

Component Types

Roact provides three built-in component types that cover the most common use cases.

Roact.Component

The base class for all stateful components. Extend it with Roact.Component:extend("ComponentName") to create a new class. Stateful components have access to self.props, self.state, and the full lifecycle API.
local Counter = Roact.Component:extend("Counter")

function Counter:init()
    self:setState({ count = 0 })
end

function Counter:render()
    return Roact.createElement("TextLabel", {
        Text = "Count: " .. tostring(self.state.count),
    })
end

Roact.PureComponent

An extension of Roact.Component that overrides shouldUpdate with a shallow equality check on both props and state. A PureComponent will skip re-rendering if its new props and state are shallowly equal to the previous values, which can offer significant performance gains when used with immutable data patterns (such as those enforced by Rodux).
PureComponent is not always faster. If your props or state contain deeply nested tables that are mutated in place, the shallow check will fail to detect changes, and your component will not re-render when it should. Use PureComponent only with immutable data.
local PureLabel = Roact.PureComponent:extend("PureLabel")

function PureLabel:render()
    -- Only re-renders when props.text actually changes
    return Roact.createElement("TextLabel", { Text = self.props.text })
end

Roact.Portal

A special component that renders its children into a Roblox Instance outside of the normal component tree. This is useful for UI elements like modal dialogs or tooltips that need to live at the top of the Instance hierarchy but be controlled by a deeply-nested component. Portals are created with Roact.createElement and require a target prop pointing to an existing Roblox Instance that is not managed by Roact.
target
Instance
required
The Roblox Instance into which the portal’s children will be placed. Must not be a Roact-managed Instance.
local Dialog = Roact.Component:extend("Dialog")

function Dialog:render()
    return Roact.createElement(Roact.Portal, {
        target = game:GetService("CoreGui"),
    }, {
        Overlay = Roact.createElement("ScreenGui", {}, {
            Frame = Roact.createElement("Frame", {
                Size = UDim2.new(1, 0, 1, 0),
                BackgroundTransparency = 0.5,
            }),
        }),
    })
end

Prop Markers

Roact exports four special constant values used as keys inside host element prop tables. Because these values must be distinguishable from ordinary string property names, they are unique Lua objects rather than strings.
ConstantDescription
Roact.EventIndex with an event name (Roact.Event.Activated) to connect a callback to that Roblox Instance event.
Roact.ChangeIndex with a property name (Roact.Change.Text) to connect a callback via GetPropertyChangedSignal.
Roact.RefAssign a ref object or function to receive a handle to the underlying Roblox Instance.
Roact.ChildrenThe key Roact uses internally to store child elements on a props table; read it in components to access children.
Full documentation for all four markers — including callback signatures, object vs. function ref forms, and the deprecated ref.current field — is on the Prop Markers page.

Special Constants

Roact.None

Roact.None is a sentinel value used to remove a field from component state when calling setState or returning from getDerivedStateFromProps. In Lua, setting a table key to nil simply omits it, so there is no way to express “please delete this key” using plain nil. Roact.None fills that gap.
function MyComponent:didMount()
    -- Removes "temporaryField" from state entirely
    self:setState({
        temporaryField = Roact.None,
    })
end

Build docs developers (and LLMs) love