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

Dedupe warnings about refs on functional components #8739

Merged
merged 3 commits into from
Jan 10, 2017

Conversation

gaearon
Copy link
Collaborator

@gaearon gaearon commented Jan 10, 2017

The warning added in #8635 is very noisy.

It was already somewhat noisy for strings, printing on every mount, but it is much more noisy for functional refs because they often change between updates, causing the warning to be printed again and again.

Before this PR, we would get warnings once per attempt to attach the ref.
After this PR, we get warnings once per callsite—to the best of our ability to tell them apart.

See individual commit messages for more information.

It's not a big problem for string refs because the ref stays the same and the warning code path runs once per mount.

However, it is super annoying for functional refs since they're often written as arrows, and thus the warning fires for every render.

Both tests are currently failing since we're mounting twice, so even the string ref case prints warnings twice.
We don't want to run getStackAddendumByID() unless we actually know we're going to print the warning.

This doesn't affect correctness. Just a performance fix.
This fixes the duplicate warnings and adds an additional test for corner cases.

Our goal is to print one warning per one offending call site, when possible.

We try to use the element source for deduplication first because it gives us the exact JSX call site location.

If the element source is not available, we try to use the owner name for deduplication.

If even owner name is unavailable, we try to use the functional component unique identifier for deduplication so that at least the warning is seen once per mounted component.
@gaearon
Copy link
Collaborator Author

gaearon commented Jan 10, 2017

@iamdustan I can't assign you in GH but I'd appreciate your review too.

ReactDebugCurrentFiber.getCurrentFiberStackAddendum()
);
let warningKey = ownerName || workInProgress._debugID || '';
const debugSource = workInProgress._debugSource;
Copy link
Contributor

Choose a reason for hiding this comment

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

_debugSource is added via a babel plugin, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is added here to the Fiber, and it is on the element from this Babel plugin (enabled by default in CRA).

Copy link
Contributor

Choose a reason for hiding this comment

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

not directly related to this PR, but are there any concerns that dev behavior may change slightly based on babel-plugins? Especially for compile-to-js implementations?

Perhaps there should be documentation added to https://facebook.github.io/react/contributing/implementation-notes.html for _debugSource?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Would be nice to add, want to send a PR?

spyOn(console, 'error');

// Prevent the Babel transform adding a displayName.
var createClassWithoutDisplayName = React.createClass;
Copy link
Contributor

Choose a reason for hiding this comment

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

if the babel plugin is updated to follow React.createClass aliases I assume this test would break?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yea. But I bet pretty hard it won't happen. :-)

expectDev(console.error.calls.count()).toBe(1);
});

it('deduplicates ref warnings based on element or owner', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

+1. this test looks very comprehensive.

Copy link
Contributor

@iamdustan iamdustan left a comment

Choose a reason for hiding this comment

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

Hey I can approve!

@gaearon gaearon added this to the 15-lopri milestone Jan 10, 2017
@gaearon gaearon merged commit bd23aa2 into facebook:master Jan 10, 2017
@gaearon gaearon deleted the dedupe-stateless-ref-warnings branch January 10, 2017 17:54
@gaearon
Copy link
Collaborator Author

gaearon commented Jan 10, 2017

Thanks for taking a look!

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.

3 participants