Components
Components are encapsulated, reusable pieces of UI that you can combine to build a complete UI.
Components accept inputs, known as props, and return elements to describe the UI that should represent those inputs.
Types of Components¶
Host Components¶
A host component is nothing more than a string that matches the name of a Roblox class. We used these in our earlier discussion about elements as the first argument to createElement
. Examples include "Frame"
, "ImageButton"
, etc.
When our component is a host component, the props that we pass to it will be turned directly into properties on the Roblox instance that the component refers to.
Function Components¶
Function components are the simplest kind of user-defined component: they're just functions that accept props as their only argument, and return some elements.
local function Greeting(props)
return Roact.createElement("TextLabel", {
Text = "Hello, " .. props.name
})
end
Stateful Components¶
Roact also has stateful components, which provide additional features like lifecycle methods and state. We'll talk about these features in a later section.
You can create a stateful component by calling Roact.Component:extend
and passing in the component's name.
local Greeting = Roact.Component:extend("Greeting")
function Greeting:render()
return Roact.createElement("TextLabel", {
Text = "Hello, " .. self.props.name
})
end
Using Components¶
In our previous examples, we passed strings to Roact.createElement
to create elements that represented Roblox Instances.
We can also pass our custom components to create elements that represent them:
local hello = Roact.createElement(Greeting, {
name = "Rick James"
})
The name
value is passed to our component as props, which we can reference as the props
argument in our function component or self.props
in our stateful component.
Components in Components¶
Components are designed to make it easy to re-use pieces of UI, so naturally, we can use components inside other components!
local function Greeting(props)
return Roact.createElement("TextLabel", {
Text = "Hello, " .. props.name
})
end
local function GreetEveryone()
return Roact.createElement("ScreenGui", {}, {
Layout = Roact.createElement("UIListLayout"),
HelloJoe = Roact.createElement(Greeting, {
name = "Joe"
}),
HelloMary = Roact.createElement(Greeting, {
name = "Mary"
})
})
end
Applications built using Roact usually have one component at the top of the tree, and include all other pieces as children.
Incrementing Counter, Part Two¶
We can revisit the incrementing counter example from the previous section, now using a function component. Changed sections are highlighted.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Roact = require(ReplicatedStorage.Roact)
-- Create a function component that represents our UI
local function Clock(props)
local currentTime = props.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
-- Create our initial UI.
local currentTime = 0
local clockElement = Roact.createElement(Clock, {
currentTime = currentTime
})
local handle = Roact.mount(clockElement, PlayerGui, "Clock UI")
-- Every second, update the UI to show our new time.
while true do
wait(1)
currentTime = currentTime + 1
handle = Roact.update(handle, Roact.createElement(Clock, {
currentTime = currentTime
}))
end