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

Warn early for non-functional event listeners #10453

Merged
merged 13 commits into from
Aug 23, 2017

Conversation

aweary
Copy link
Contributor

@aweary aweary commented Aug 13, 2017

Resolves #10407

Brandon Dail added 3 commits August 13, 2017 14:04
To avoid triggering the non-functional event listener component
This should warn from ReactDOMFiberComponent, but we just ignore it here
@aweary aweary changed the title Warn early non function event listeners Warn early for non-functional event listeners Aug 13, 2017
@@ -24,6 +24,8 @@ describe('EventPluginHub', () => {
});

it('should prevent non-function listeners, at dispatch', () => {
// ReactDOMFiberComponent warns for non-function event listeners
spyOn(console, 'error');
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 still add an expectation. So that it doesn't emit some other unwanted warning by mistake in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in c377e35

@@ -227,6 +236,9 @@ function setInitialDOMProperties(
// Noop
} else if (registrationNameModules.hasOwnProperty(propKey)) {
if (nextProp) {
if (__DEV__) {
warnForInvalidEventListener(propKey, nextProp);
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 a very hot path. How do you feel about hoisting the condition right here (duplicating it) and only calling the function in the bad case?

ReactDOM.render(<Example />, container);
expectDev(console.error.calls.count()).toBe(1);
expectDev(console.error.calls.argsFor(0)[0]).toContain(
'Expected onClick listener to be a function, instead got type string',
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we provide component stack here?

@aweary
Copy link
Contributor Author

aweary commented Aug 14, 2017

@gaearon feedback addressed 👍

'Expected onClick listener to be a function, instead got type string',
);
} else {
expectDev(console.error.calls.count()).toBe(0);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This warning isn't included in stack since it fails early

@@ -913,7 +917,7 @@ describe('ReactDOMFiber', () => {
]);
});

it('should warn for non-functional event listeners', () => {
it.only('should warn for non-functional event listeners', () => {
spyOn(console, 'error');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Only

@@ -913,6 +917,24 @@ describe('ReactDOMFiber', () => {
]);
});

it.only('should warn for non-functional event listeners', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Need to fix this, otherwise should be good to go

@@ -913,6 +917,24 @@ describe('ReactDOMFiber', () => {
]);
});

it.only('should warn for non-functional event listeners', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

-.only

@@ -227,6 +238,9 @@ function setInitialDOMProperties(
// Noop
} else if (registrationNameModules.hasOwnProperty(propKey)) {
if (nextProp) {
if (__DEV__ && typeof nextProp !== 'function') {
Copy link
Collaborator

@sebmarkbage sebmarkbage Aug 14, 2017

Choose a reason for hiding this comment

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

You can move this typeof nextProp !== 'function' assertion into the warnForInvalidEventListener function. E.g. as the first argument to warning(). Makes it easier to keep in sync and update. E.g. if we want to support other type of listeners like {handleEvent() { }}.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's how it used to do but I wanted to avoid extra overhead for calls for every single prop. These things are small but sometimes add up (like when we fixed DEV performance in 15.3).

Copy link
Collaborator

Choose a reason for hiding this comment

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

But I don't feel strongly. Didn't think about the object case where it could change.

@sebmarkbage
Copy link
Collaborator

This only covers ReactDOM. We have the same issue in ReactNative but there we don't need to do any early work to set up listeners so we don't have the equivalent paths.

var warnForInvalidEventListener = function(registrationName, listener) {
warning(
false,
'Expected %s listener to be a function, instead got type %s%s',
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: I think we usually end warnings with periods (before the stack) so that they look like sentences.

@gaearon gaearon merged commit 34780da into facebook:master Aug 23, 2017
@bvaughn bvaughn mentioned this pull request Sep 7, 2017
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.

4 participants