Releases: Roblox/roact
1.4.4
What's Changed
- Gracefully handle double unmount. by @dougbankspersonal in #327
- Fixed typos in documentation by @MalikIdreesHasanKhan in #328
- Remove the warning for setState on unmounted components by @chriscerie in #323
- Add Wally manifest file by @LPGhatguy in #314
- Update GHA non-cached third party actions by @ZoteTheMighty in #365
- Update setup-foreman action path by @ZoteTheMighty in #366
- Setup basic Luau analysis by @ghostnaps in #372
New Contributors
- @MalikIdreesHasanKhan made their first contribution in #328
- @ghostnaps made their first contribution in #372
Full Changelog: v1.4.3...v1.4.4
v1.4.2
v1.4.1
Patches behavior behind the tempFixUpdateChildrenReEntrancy
config value to address additional reentrancy cases.
Changes since 1.4.0
v1.4.0
A number of small changes to error messaging and performance, as well as a forwardRef
API that matches React.
Changes since 1.3.0
- Introduce forwardRef (#307).
- Fixed a bug where the Roact tree could get into a broken state when processing changes to child instances outside the standard lifecycle.
- This change is behind the config value tempFixUpdateChildrenReEntrancy (#301)
- Added color schemes for documentation based on user preference (#290).
- Fixed stack trace level when throwing an error in
createReconciler
(#297). - Optimized the memory usage of 'createSignal' implementation. (#304)
- Added component name to property validation error message (#275)
v1.3.0
This release introduces the new Context API
Changes Since 1.2.0
- Released new Context API, available via
Roact.createContext
v1.2.0
This release fixes a major bug with fragments and a minor behavioral inconsistency with setState
.
Changes Since 1.1.0
v1.1.0
This release fixes a minor reconciliation bug and introduces a new binding API, Roact.joinBindings
.
Changes Since 1.0.0
- Fixed an issue where updating a host element with children to an element with
nil
children caused the old children to not be unmounted. (#210) - Added
Roact.joinBindings
, which allows combining multiple bindings into a single binding that can be mapped. (#208)
Roact.joinBindings
The new joinBindings
API can be used to combine multiple bindings and use them to create a new binding!
You can use this to implement flexible sizing without going through the reconciler, for example:
local function Flex()
local aSize, setASize = Roact.createBinding(Vector2.new())
local bSize, setBSize = Roact.createBinding(Vector2.new())
return Roact.createElement("Frame", {
Size = Roact.joinBindings({aSize, bSize}):map(function(sizes)
local sum = Vector2.new()
for _, size in ipairs(sizes) do
sum = sum + size
end
return UDim2.new(0, sum.X, 0, sum.Y)
end),
}, {
A = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, 30),
[Roact.Change.AbsoluteSize] = function(instance)
setASize(instance.Size)
end,
}),
B = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, 30),
Position = aSize:map(function(size)
return UDim2.new(0, 0, 0, size.Y)
end),
[Roact.Change.AbsoluteSize] = function(instance)
setBSize(instance.Size)
end,
}),
})
end
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.
v0.2.0
This is the first non-prerelease release of Roact, and the last one before we merge in a large refactor from our current development branch, new-reconciler
.
We consider this release to be a stable release for existing projects using Roact prereleases.
Later today, we'll be publishing Roact 1.0, which includes almost a year of significant refactoring work and introduces a substantial number of features. We wanted to mark this release as the last version using the old Roact internals that have been proven stable in projects like the Roblox iOS, Android, and Xbox applications.
Changes since April 15th, 2019 Prerelease
- Deprecated
Roact.reconcile
in favor ofRoact.update
(#194) - Removed some undocumented APIs:
Roact.getGlobalConfigValue
, which let users read the current internal configuration.Roact.Element
, which let users figure out whether something is a Roact element. We'll introduce a proper type-checking API at a later date.
Prerelease 2019-04-15
This prerelease is a roll-up of the changes since the latest prerelease, which was awhile ago!
Since the last prerelease, we've been working out of a new branch that we've been grooming to become Roact 1.0. It's on the new-reconciler
branch if you're interested in checking it out, and it'll be merged to master within the next month or so hopefully!