Skip to content
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

Merged
merged 5 commits into from
Oct 26, 2016
Merged

[Fiber] String refs and owner tracking #8099

merged 5 commits into from
Oct 26, 2016

Conversation

acdlite
Copy link
Collaborator

@acdlite acdlite commented Oct 26, 2016

Implements string refs using callback closures.

Still need to update existing ref tests to work with Fiber.

@acdlite acdlite changed the title [Fiber ] String refs and owner tracking [Fiber] String refs and owner tracking Oct 26, 2016
const inst = ownerFiber.stateNode;
const ref = function(value) {
const refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
refs[element.ref] = value;
Copy link
Collaborator

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?
Copy link
Collaborator

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;
Copy link
Collaborator

@sebmarkbage sebmarkbage Oct 26, 2016

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.

Copy link
Collaborator Author

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);
Copy link
Collaborator

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.

Copy link
Collaborator Author

@acdlite acdlite Oct 26, 2016

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) {
Copy link
Collaborator

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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is doesn't reset it if the render throws. We should probably just move ReactCurrentOwner.current = null; out to @gaearon's top level try-block in #8095. So that we just reset it when we're completely done reconciling.

Copy link
Collaborator Author

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

Copy link
Collaborator

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! :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That also works :)

@sebmarkbage
Copy link
Collaborator

Alright. Accepted, pending comments.

@@ -47,6 +48,7 @@ const {
const isArray = Array.isArray;

const {
ClassComponent,
Copy link
Contributor

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?

Copy link
Collaborator Author

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

@acdlite
Copy link
Collaborator Author

acdlite commented Oct 26, 2016

653 tests failed, 3 tests skipped, 838 tests passed

if (currentOwner && typeof currentOwner._debugID === 'number') {
var id = currentOwner && currentOwner._debugID;
info += ReactComponentTreeHook.getStackAddendumByID(id);
}
Copy link
Collaborator

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.

Copy link
Collaborator Author

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
@sebmarkbage
Copy link
Collaborator

Looks like you still have one more Flow error.

@acdlite
Copy link
Collaborator Author

acdlite commented Oct 26, 2016

@sebmarkbage Yeah can't figure it out yet :(

const ref = function(value) {
const refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
refs[stringRef] = value;
}
Copy link
Collaborator

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) {
Copy link
Collaborator

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.

Copy link
Collaborator

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.

@gaearon
Copy link
Collaborator

gaearon commented Oct 26, 2016

The Flow issue is because ReactCurrentOwner.current can now be a Fiber, so there's no guarantee _warnedAboutRefsInRender exists on it.

@gaearon gaearon merged commit d5eff3b into master Oct 26, 2016
@gaearon gaearon deleted the fiberstringrefs branch October 26, 2016 13:37
@gaearon
Copy link
Collaborator

gaearon commented Oct 26, 2016

I fixed it up so we can get this merged and avoid conflicts later.

@acdlite
Copy link
Collaborator Author

acdlite commented Oct 26, 2016

Ha that's one way to fix it! Thanks for merging

@gaearon
Copy link
Collaborator

gaearon commented Oct 26, 2016

Yea since it's RN I don't think it's an issue, we won't get there very soon anyway.

@gaearon
Copy link
Collaborator

gaearon commented Oct 26, 2016

We could also add $$typeof to internal instances and Fibers for nominal typing.

acusti pushed a commit to brandcast/react that referenced this pull request Mar 15, 2017
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants