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 is built on the principle that it’s much easier to build UI declaratively. When something changes, Roact rebuilds the UI virtually and then applies the minimal necessary changes to the actual Roblox Instances. For the vast majority of projects this process is fast enough out of the box — but understanding how it works helps you recognize the rare situations where optimization is worthwhile.

How Roact Works

Every time a component renders, Roact produces a virtual tree: a lightweight Lua table description of what the UI should look like. Roact then diffs this new virtual tree against the previous one and calculates the smallest set of changes required. Only those differences are written back to real Roblox Instances. This approach has two important implications:
  • Rendering is cheap by default. Creating Lua tables and comparing them is far less expensive than creating or modifying Roblox Instances directly.
  • Reconciliation has overhead. Every state or prop change triggers a diff pass. On large trees with many components, these passes accumulate — and because Roact runs in Lua, even lightweight operations add up faster than they would in a compiled language.

When Performance Can Become a Concern

For most projects, Roact’s default behavior is more than fast enough. Performance overhead tends to appear only when:
  • A tree is very large — hundreds of components rendered simultaneously.
  • A high-frequency state change (such as a value updating every frame) triggers re-renders across many components that haven’t actually changed.
  • Components perform expensive work inside render that runs even when their props or state are identical to the previous values.
If your UI feels responsive and your frame budget isn’t under pressure, you likely don’t need to change anything.

The Two Main Optimization Strategies

When optimization is warranted, the techniques available in Roact fall into two categories:

Reduce Reconciliation Work

Tell Roact that certain components don’t need to re-render. Use shouldUpdate or PureComponent to skip diff passes when nothing meaningful has changed.

Use Stable Keys

Give child elements stable, unique keys so Roact can match them across renders without having to update every sibling when the list changes order.
Both strategies are covered in detail on the Reduce Reconciliation Work page.

Techniques at a Glance

TechniqueWhat It DoesBest For
shouldUpdateCustom logic to skip re-rendersComponents with complex, known update conditions
PureComponentShallow equality check on props and stateComponents used with immutable data (e.g. Rodux)
Stable keysKeeps child Instances matched by identityLists where items are added, removed, or reordered

Optimization Guidelines

Before reaching for any of these tools, consider the following:
  • Measure first. Roact’s reconciliation is often faster than it appears. Profile your experience before assuming a component is the bottleneck.
  • Prefer PureComponent over manual shouldUpdate. Manual implementations of shouldUpdate are easy to get wrong and can introduce subtle bugs where components stop updating when they should.
  • Stable keys are low-risk and high-reward. Switching list keys from numeric indexes to stable IDs rarely introduces bugs and can meaningfully reduce the number of Instance property writes Roblox has to process.
For simple and medium-sized projects, performance is rarely an issue with Roact’s defaults. Premature optimization adds complexity and increases the risk of bugs — particularly with shouldUpdate, where returning false at the wrong time can cause your UI to silently stop reflecting the current state. Start with clean, readable component code and optimize only when you have a measured reason to do so.

Build docs developers (and LLMs) love