diff --git a/src/renderers/__tests__/EventPluginHub-test.js b/src/renderers/__tests__/EventPluginHub-test.js index 03b33abe00b00..4ad5bd3db2e92 100644 --- a/src/renderers/__tests__/EventPluginHub-test.js +++ b/src/renderers/__tests__/EventPluginHub-test.js @@ -16,22 +16,33 @@ jest.mock('isEventSupported'); describe('EventPluginHub', () => { var React; var ReactTestUtils; + var ReactDOMFeatureFlags; beforeEach(() => { jest.resetModules(); React = require('react'); ReactTestUtils = require('react-dom/test-utils'); + ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); }); it('should prevent non-function listeners, at dispatch', () => { + spyOn(console, 'error'); var node = ReactTestUtils.renderIntoDocument(
, ); expect(function() { ReactTestUtils.SimulateNative.click(node); }).toThrowError( - 'Expected onClick listener to be a function, instead got type string', + 'Expected `onClick` listener to be a function, instead got a value of `string` type.', ); + if (ReactDOMFeatureFlags.useFiber) { + expectDev(console.error.calls.count()).toBe(1); + expectDev(console.error.calls.argsFor(0)[0]).toContain( + 'Expected `onClick` listener to be a function, instead got a value of `string` type.', + ); + } else { + expectDev(console.error.calls.count()).toBe(0); + } }); it('should not prevent null listeners, at dispatch', () => { diff --git a/src/renderers/dom/fiber/ReactDOMFiberComponent.js b/src/renderers/dom/fiber/ReactDOMFiberComponent.js index b31104d479c28..dbab479acb659 100644 --- a/src/renderers/dom/fiber/ReactDOMFiberComponent.js +++ b/src/renderers/dom/fiber/ReactDOMFiberComponent.js @@ -34,6 +34,7 @@ var setTextContent = require('setTextContent'); if (__DEV__) { var warning = require('fbjs/lib/warning'); + var {getCurrentFiberStackAddendum} = require('ReactDebugCurrentFiber'); var ReactDOMInvalidARIAHook = require('ReactDOMInvalidARIAHook'); var ReactDOMNullInputValuePropHook = require('ReactDOMNullInputValuePropHook'); var ReactDOMUnknownPropertyHook = require('ReactDOMUnknownPropertyHook'); @@ -122,6 +123,16 @@ if (__DEV__) { warning(false, 'Extra attributes from the server: %s', names); }; + var warnForInvalidEventListener = function(registrationName, listener) { + warning( + false, + 'Expected `%s` listener to be a function, instead got a value of `%s` type.%s', + registrationName, + typeof listener, + getCurrentFiberStackAddendum(), + ); + }; + var testDocument; // Parse the HTML and read it back to normalize the HTML string so that it // can be used for comparison. @@ -227,6 +238,9 @@ function setInitialDOMProperties( // Noop } else if (registrationNameModules.hasOwnProperty(propKey)) { if (nextProp) { + if (__DEV__ && typeof nextProp !== 'function') { + warnForInvalidEventListener(propKey, nextProp); + } ensureListeningTo(rootContainerElement, propKey); } } else if (isCustomComponentTag) { @@ -740,6 +754,9 @@ var ReactDOMFiberComponent = { } else if (registrationNameModules.hasOwnProperty(propKey)) { if (nextProp) { // We eagerly listen to this even though we haven't committed yet. + if (__DEV__ && typeof nextProp !== 'function') { + warnForInvalidEventListener(propKey, nextProp); + } ensureListeningTo(rootContainerElement, propKey); } if (!updatePayload && lastProp !== nextProp) { @@ -980,6 +997,9 @@ var ReactDOMFiberComponent = { } } } else if (registrationNameModules.hasOwnProperty(propKey)) { + if (__DEV__ && typeof nextProp !== 'function') { + warnForInvalidEventListener(propKey, nextProp); + } if (nextProp) { ensureListeningTo(rootContainerElement, propKey); } diff --git a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js index 4a4fdbe808ffb..bca5ad38a5be2 100644 --- a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js +++ b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js @@ -18,6 +18,10 @@ var ReactTestUtils = require('react-dom/test-utils'); var PropTypes = require('prop-types'); describe('ReactDOMFiber', () => { + function normalizeCodeLocInfo(str) { + return str && str.replace(/\(at .+?:\d+\)/g, '(at **)'); + } + var container; var ReactFeatureFlags; @@ -913,6 +917,24 @@ describe('ReactDOMFiber', () => { ]); }); + it('should warn for non-functional event listeners', () => { + spyOn(console, 'error'); + class Example extends React.Component { + render() { + return ; + } + } + ReactDOM.render(