Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

createRef API #92

Merged
merged 19 commits into from
May 16, 2018
Merged

createRef API #92

merged 19 commits into from
May 16, 2018

Conversation

AmaranthineCodices
Copy link
Contributor

Closes #70.

Adds a createRef function to the global Roact namespace. createRef returns an object reference with a current property that can be used like existing functional refs. Example usage:

local SomeTextbox = Roact.Component:extend("SomeTextbox")

function SomeTextbox:init()
    self.textboxRef = Roact.createRef()
end

function SomeTextbox:render()
    return Roact.createElement("TextBox", {
        -- ...
        [Roact.Ref] = self.textboxRef
    })
end

function SomeTextbox:didMount()
    self.textboxRef.current:CaptureFocus()
end

@coveralls
Copy link

coveralls commented May 15, 2018

Coverage Status

Coverage increased (+0.4%) to 90.24% when pulling b139cc3 on AmaranthineCodices:createRef into 93358ca on Roblox:master.

@AmaranthineCodices AmaranthineCodices mentioned this pull request May 15, 2018
2 tasks
Copy link
Contributor

@LPGhatguy LPGhatguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hooray!

Minor actual code changes, mostly just want to push some of the docs into a new PR after this one!

@@ -72,6 +79,10 @@ If you're writing a new functional or stateful element that needs to be used lik
Use `Roact.Ref` as a key into the props of a primitive element to receive a handle to the underlying Roblox Instance.

```lua
Roact.createElement("Frame", {
[Roact.Ref] = objectReference,
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example seems sort of incomplete -- we should break the functional and object ref examples into two separate blocks and label what they do!

When a user clicks on the outer `ImageButton`, the `captureFocus` method will be called and the `TextBox` instance will get focus as if it had been clicked on directly.

## Functional Refs
Roact allows you to use functions as refs. The function will be called with the Roblox object that Roact creates. For example, this is the SearchBar component from above, modified to use functional refs instead of object refs:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move the guie changes to a new PR? There are quite a few more things we need to catch across the docs, and I want to let the API simmer a bit before recommending it as the new default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, done!

local ref = element.props[Core.Ref]

if ref then
applyRef(ref, nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this condition into applyRef itself, which would make all of these invocations a bit cleaner!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'd help clean some stuff up, yeah!

Correctly handles both function-style and object-style refs.
]]
local function applyRef(ref, newRbx)
if not ref then return end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's explicitly check if ref == nil and then put the return statement on its own line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed now!

it("should support tostring on refs", function()
local ref = createRef()
expect(tostring(ref)).to.equal("RoactReference(\"nil\")")
end)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to test tostring on these, let's also verify that they take on the name of their current value if set, too!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair, done!


local refMetatable = {
__tostring = function(self)
return ("RoactReference(%q)"):format(tostring(self.current))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it now, do you think we should just format these with %s instead of %q? Since they'll mostly be Roblox objects, I don't know if it makes much sense to quote them!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true - I'm used to quoting everything, but in this case it doesn't do much good! Fixed now.

@@ -323,7 +335,7 @@ function Reconciler._reconcileInternal(instanceHandle, newElement)

-- Cancel the old ref before we make changes. Apply the new one after.
if refChanged and oldRef then
oldRef(nil)
applyRef(oldRef, nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to update the branch on line 349 that applies newRef as well! It's calling newRef as a function.

expect(currentRbx).to.be.ok()
Reconciler.unmount(handle)
expect(currentRbx).to.never.be.ok()
end)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a test that makes sure that refs can be unattached and attached through Reconciler.reconcile?

@LPGhatguy LPGhatguy merged commit b25a063 into Roblox:master May 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants