When a component needs to produce several sibling elements, the instinct is often to wrap them all inside a containerDocumentation 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.
Frame. That wrapper becomes a real Roblox Instance, however — it sits in the hierarchy, breaks layout components like UIListLayout, and clutters the object tree with structure that serves no purpose other than satisfying Roact’s single-root requirement. Fragments solve this cleanly: Roact.createFragment lets a component return a collection of elements that each become direct children of the component’s parent, with no wrapper Instance ever created.
The Problem: Unwanted Wrapper Instances
Suppose you are building a team roster UI. ATeamList component owns a Frame with a UIListLayout so the children stack vertically. You extract the label rows into a separate TeamLabels component, but that component needs to return two TextLabels — so you wrap them in a Frame.
UIListLayout in TeamList only affects its direct siblings, so this extra Frame layer breaks the layout entirely. The resulting Roblox hierarchy looks like this:
TextLabels are nested one level too deep and are invisible to the UIListLayout.
The Fix: Roact.createFragment
Roact.createFragment was added in Roact 1.0.0.Roact.createFragment takes a table of named elements and returns a fragment — a lightweight object that Roact flattens into the parent’s children when mounting. No wrapper Instance is ever inserted into the DataModel.
- Without Fragments
- With Fragments
UIListLayout does not apply to the labels because they are not direct siblings of the layout component.Frame, the UIListLayout stacks them exactly as intended.
When to Use Fragments vs. a Real Container
| Situation | Recommendation |
|---|---|
Children need a layout component (UIListLayout, UIGridLayout) that lives in the same parent | Use a fragment — avoid an extra wrapper that breaks the layout |
| The grouping boundary is a meaningful visual container (background, padding, clipping) | Use a real Frame — the container genuinely belongs in the hierarchy |
| A component is composing a list and the caller controls the layout | Use a fragment so the caller’s layout sees all items as siblings |
You need Roblox properties like Size, BackgroundColor3, or ClipsDescendants on the grouping node | Use a real element — fragments have no Instance and carry no properties |
Frame whose only purpose is to satisfy the single-root rule.