v1.0.0
This release is the culmination of almost one year of work improving Roact's internals to pave the way for new features, optimizations, and ergonomic improvements.
We encourage existing projects to upgrade to 1.0.0 when possible. We feel that the improvements it brings over 0.2.0 and previous releases are substantial!
Changes Since 0.2.0
- Added Fragments, which reduces the need for many container instances. (#172)
- Added Bindings, which enables easy surgical updates to instances without using refs. (#159)
- Added opt-in runtime type checking across the entire Roact API. (#188)
- Added support for prop validation akin to React's
propTypes
. - Changed
Component:setState
to be deferred if it's called while Roact is updating a component. (#183) - Changed events connected via
Roact.Event
andRoact.Change
triggered by a Roact update to be deferred until Roact is done updating the instance. - Improved and consolidated terminology across the board.
- Improved errors to be much more informative and clear.
Fragments
The Roact.createFragment
API enables returning multiple components from the render function of a function or stateful component.
Where we would previously have to create dummy Folder
instances or nest elements endlessly, we can now return a fragment containing multiple objects!
Before, in 0.2.0:
local function Connectors()
return Roact.createElement("Folder", {
Keyboard = Roact.createElement(KeyboardConnector),
Mouse = Roact.createElement(MouseConnector),
})
end
Now, in 1.0.0:
local function Connectors()
return Roact.createFragment({
Keyboard = Roact.createElement(KeyboardConnector),
Mouse = Roact.createElement(MouseConnector),
})
end
Bindings
Bindings are a great way to build animations, as well as a good way to improve performance in cases where Roact isn't quite keeping up.
Check out our brand new bindings and refs guide for an introduction to how bindings can be used.
Bindings can be used to create an efficient, safe, and performant Roact fit-to-contents implementation:
local FitList = Roact.Component:extend("FitList")
function FitList:init()
self.size, self.setSize = Roact.createBinding(Vector2.new())
end
function FitList:render()
local children = {
Layout = Roact.createElement("UIListLayout", {
[Roact.Change.AbsoluteContentSize] = function(instance)
self.setSize(instance.AbsoluteContentSize)
end,
})
}
for key, child in pairs(self.props[Roact.Children]) do
children[key] = child
end
return Roact.createElement("Frame", {
Size = self.size:map(function(absoluteSize)
return UDim2.new(0, absoluteSize.X, 0, absoluteSize.Y)
end),
}, children)
end
Prop Validation
Set the validateProps
value on your stateful component class to enable opting into strong type checking every time props update.
Prop validation is opt-in! To enable it in your project, use Roact.setGlobalConfig
once somewhere in your project:
Roact.setGlobalConfig({
propValidation = true,
})
When paired with libraries like t by Osyris, it's easy to make sure your components are accepting the correct props:
local CoolTextLabel = Roact.Component:extend("CoolTextLabel")
CoolTextLabel.validateProps = t.strictInterface({
text = t.string,
layoutOrder = t.optional(t.integer),
})
function CoolTextLabel:render()
return Roact.createElement("TextLabel", {
Size = UDim2.new(0, 400, 0, 400),
Text = self.props.text,
LayoutOrder = self.props.layoutOrder,
})
end
Improved Terminology & Errors
We have a huge new suite of documentation and error messages that should make everything more clear when you run into problems.