This repository has been archived by the owner on Dec 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
306 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
In certain situations, such as when building reusable and customizable components, props may be composed of Roact objects, such as an element or a component. | ||
|
||
To facilitate safer development for these kinds of situations, Roact provides the `Roact.typeOf` and `Roact.isComponent` functions to help validate these objects. | ||
|
||
## Roact Object Type Validation | ||
|
||
Suppose we want to write a `Header` component with a prop for the title child element: | ||
```lua | ||
local Header = Component:extend("Header") | ||
|
||
function Header:render() | ||
local title = props.title | ||
|
||
return Roact.createElement("Frame", { | ||
-- Props for Frame... | ||
}, { | ||
Title = title | ||
}) | ||
end | ||
``` | ||
|
||
Now suppose we want to validate that `title` is actually an element using [validateProps](../../api-reference/#validateprops). With `Roact.typeOf` we can be certain we have a Roact Element: | ||
```lua | ||
Header.validateProps = function() | ||
local title = props.title | ||
|
||
if Roact.typeOf(title) == Roact.Type.Element then | ||
return true | ||
end | ||
|
||
return false, "prop title is not an element" | ||
end | ||
``` | ||
|
||
## Component Type Validation | ||
|
||
In some cases, a component will be more preferable as a prop than an element. `Roact.isComponent` can be used to see if a value is a plausible component and thus can be passed to `Roact.createElement`. | ||
|
||
```lua | ||
local Header = Component:extend("Header") | ||
|
||
Header.validateProps = function() | ||
local title = props.title | ||
|
||
if Roact.isComponent(title) then | ||
return true | ||
end | ||
|
||
return false, "prop title can not be an element" | ||
end | ||
|
||
function Header:render() | ||
local title = props.title | ||
return Roact.createElement("Frame", { | ||
-- Props for Frame... | ||
}, { | ||
Title = Roact.isComponent(title) and Roact.createElement(title, { | ||
-- Props for Title... | ||
}) | ||
}) | ||
end | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
--[[ | ||
Mirrors a subset of values from Type.lua for external use, allowing | ||
type checking on Roact objects without exposing internal Type symbols | ||
TypeMirror: { | ||
Type: Roact.Type, | ||
typeOf: function(value: table) -> Roact.Type | nil | ||
} | ||
]] | ||
|
||
local Type = require(script.Parent.Type) | ||
local Symbol = require(script.Parent.Symbol) | ||
local strict = require(script.Parent.strict) | ||
|
||
local ALLOWED_TYPES = { | ||
Type.Binding, | ||
Type.Element, | ||
Type.HostChangeEvent, | ||
Type.HostEvent, | ||
Type.StatefulComponentClass, | ||
Type.StatefulComponentInstance, | ||
Type.VirtualTree | ||
} | ||
|
||
local MirroredType = {} | ||
for _, type in ipairs(ALLOWED_TYPES) do | ||
local name = Type.nameOf(type) | ||
MirroredType[name] = Symbol.named("Roact" .. name) | ||
end | ||
|
||
setmetatable(MirroredType, { | ||
__tostring = function() | ||
return "RoactType" | ||
end | ||
}) | ||
|
||
strict(MirroredType, "Type") | ||
|
||
local Mirror = { | ||
typeList = ALLOWED_TYPES, | ||
Type = MirroredType, | ||
typeOf = function(value) | ||
local name = Type.nameOf(Type.of(value)) | ||
if not name then | ||
return nil | ||
end | ||
return MirroredType[name] | ||
end, | ||
} | ||
|
||
strict(Mirror, "TypeMirror") | ||
|
||
return Mirror |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
return function() | ||
local Type = require(script.Parent.Type) | ||
local Mirror = require(script.Parent.TypeMirror) | ||
|
||
describe("Type", function() | ||
it("should return a mirror of an internal type", function() | ||
local name = Type.nameOf(Type.Element) | ||
local mirroredType = Mirror.Type[name] | ||
expect(mirroredType).to.equal(Mirror.Type.Element) | ||
end) | ||
|
||
it("should not return the actual internal type", function() | ||
local name = Type.nameOf(Type.Element) | ||
local mirroredType = Mirror.Type[name] | ||
expect(mirroredType).to.never.equal(Type.Element) | ||
end) | ||
|
||
it("should include all allowed types", function() | ||
for _, type in ipairs(Mirror.typeList) do | ||
local name = Type.nameOf(type) | ||
local mirroredType = Mirror.Type[name] | ||
expect(mirroredType).to.be.ok() | ||
end | ||
end) | ||
|
||
it("should not include any other types", function() | ||
local name = Type.nameOf(Type.VirtualNode) | ||
local success = pcall(function() | ||
local _ = Mirror.Type[name] | ||
end) | ||
expect(success).to.equal(false) | ||
end) | ||
end) | ||
|
||
describe("typeOf", function() | ||
it("should return nil if the value is not a valid type", function() | ||
expect(Mirror.typeOf(1)).to.equal(nil) | ||
expect(Mirror.typeOf(true)).to.equal(nil) | ||
expect(Mirror.typeOf"test").to.equal(nil) | ||
expect(Mirror.typeOf(print)).to.equal(nil) | ||
expect(Mirror.typeOf({})).to.equal(nil) | ||
expect(Mirror.typeOf(newproxy(true))).to.equal(nil) | ||
end) | ||
|
||
it("should return the assigned type", function() | ||
local test = { | ||
[Type] = Type.Element | ||
} | ||
|
||
expect(Mirror.typeOf(test)).to.equal(Mirror.Type.Element) | ||
end) | ||
end) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
local Portal = require(script.Parent.Portal) | ||
local Type = require(script.Parent.Type) | ||
|
||
-- Returns true if the provided object can be used by Roact.createElement | ||
return function(value) | ||
local valueType = type(value) | ||
|
||
local isComponentClass = Type.of(value) == Type.StatefulComponentClass | ||
local isValidFunctionComponentType = valueType == "function" | ||
local isValidHostType = valueType == "string" | ||
local isPortal = value == Portal | ||
|
||
return isComponentClass or isValidFunctionComponentType or isValidHostType or isPortal | ||
end |
Oops, something went wrong.