-
Notifications
You must be signed in to change notification settings - Fork 46.8k
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
Warn early for non-functional event listeners #10453
Conversation
To avoid triggering the non-functional event listener component
This should warn from ReactDOMFiberComponent, but we just ignore it here
@@ -24,6 +24,8 @@ describe('EventPluginHub', () => { | |||
}); | |||
|
|||
it('should prevent non-function listeners, at dispatch', () => { | |||
// ReactDOMFiberComponent warns for non-function event listeners | |||
spyOn(console, 'error'); |
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 still add an expectation. So that it doesn't emit some other unwanted warning by mistake in the future.
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.
Done in c377e35
@@ -227,6 +236,9 @@ function setInitialDOMProperties( | |||
// Noop | |||
} else if (registrationNameModules.hasOwnProperty(propKey)) { | |||
if (nextProp) { | |||
if (__DEV__) { | |||
warnForInvalidEventListener(propKey, nextProp); |
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 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', |
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.
Can we provide component stack here?
@gaearon feedback addressed 👍 |
'Expected onClick listener to be a function, instead got type string', | ||
); | ||
} else { | ||
expectDev(console.error.calls.count()).toBe(0); |
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 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'); |
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.
Only
@@ -913,6 +917,24 @@ describe('ReactDOMFiber', () => { | |||
]); | |||
}); | |||
|
|||
it.only('should warn for non-functional event listeners', () => { |
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.
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', () => { |
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.
-.only
@@ -227,6 +238,9 @@ function setInitialDOMProperties( | |||
// Noop | |||
} else if (registrationNameModules.hasOwnProperty(propKey)) { | |||
if (nextProp) { | |||
if (__DEV__ && typeof nextProp !== 'function') { |
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.
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() { }}
.
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'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).
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.
But I don't feel strongly. Didn't think about the object case where it could change.
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', |
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.
Nit: I think we usually end warnings with periods (before the stack) so that they look like sentences.
Resolves #10407