-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fiber] String refs and owner tracking #8099
Conversation
const inst = ownerFiber.stateNode; | ||
const ref = function(value) { | ||
const refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; | ||
refs[element.ref] = value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should store the ref string in a separate variable so that we don't capture the entire element and all its props in the closure.
function transferRef(fiber: Fiber, element: ReactElement<any>) { | ||
if (typeof element.ref === 'string' && element._owner) { | ||
// Should we check if this string refs is equal to the previous string ref | ||
// and reuse it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if it is faster or not actually. But we could try attaching string/owner as properties on the function. We only pay for it if you use it.
@@ -151,7 +152,13 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>, s | |||
} | |||
} | |||
|
|||
var nextChildren = fn(props); | |||
if (__DEV__) { | |||
ReactCurrentOwner.current = workInProgress; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we decided that we didn't need this for functional components? EDIT: Oh, it is DEV only. nvm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought what we decided was we didn't need it when constructing a class component. Still need it for rendering a functional component. Might be best to remove this until it's actually needed regardless.
if (typeof element.ref === 'string' && element._owner) { | ||
// Should we check if this string refs is equal to the previous string ref | ||
// and reuse it? | ||
const ownerFiber : ?Fiber = (element._owner : any); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not guaranteed to be a Fiber and it is not guaranteed to be a ClassComponent
since you attach owners to functional components too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah I even imported ClassComponent
to do the comparison but then forgot :D
@@ -62,6 +64,24 @@ const { | |||
Deletion, | |||
} = ReactTypeOfSideEffect; | |||
|
|||
function transferRef(fiber: Fiber, element: ReactElement<any>) { | |||
if (typeof element.ref === 'string' && element._owner) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is a string and there is no owner, we should probably not set the fiber.ref to a string. Maybe move the second condition inside.
const nextChildren = instance.render(); | ||
ReactCurrentOwner.current = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool I'll wait until that one gets merged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or you can just add it at the end of performWork without the try/finally so that we can land this and get some test scores up! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That also works :)
Alright. Accepted, pending comments. |
@@ -47,6 +48,7 @@ const { | |||
const isArray = Array.isArray; | |||
|
|||
const { | |||
ClassComponent, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like ClassComponent
isn't used anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I imported it for this purpose but forgot: https://github.com/facebook/react/pull/8099/files#r85031873
:D
e221ec0
to
aa14cc2
Compare
|
if (currentOwner && typeof currentOwner._debugID === 'number') { | ||
var id = currentOwner && currentOwner._debugID; | ||
info += ReactComponentTreeHook.getStackAddendumByID(id); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually about to try to make this file work with Fiber but this is fine too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah tbh I barely looked at what this file does; just trying to get it merged for now :D
Still one remaining type error that I'm not sure how to fix
6c8c3f3
to
338683f
Compare
Looks like you still have one more Flow error. |
@sebmarkbage Yeah can't figure it out yet :( |
const ref = function(value) { | ||
const refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; | ||
refs[stringRef] = value; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing semicolon.
return; | ||
} | ||
const inst = ownerFiber.stateNode; | ||
const ref = function(value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function won't get a name. We should make any functions calling user code named for better stack traces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, I misunderstood. This doesn't call into user code.
The Flow issue is because |
I fixed it up so we can get this merged and avoid conflicts later. |
Ha that's one way to fix it! Thanks for merging |
Yea since it's RN I don't think it's an issue, we won't get there very soon anyway. |
We could also add |
* Implement string refs using callback closures * Merge Fiber type to avoid Flow intersection bugs Still one remaining type error that I'm not sure how to fix * Fix Flow issue with an unsafe cast * Fix missing semicolon * Add a type import I missed earlier
Implements string refs using callback closures.
Still need to update existing ref tests to work with Fiber.