diff --git a/packages/react-reconciler/src/__tests__/ReactPure-test.internal.js b/packages/react-reconciler/src/__tests__/ReactPure-test.internal.js index 8f52da5a98adc..2813e33f9d95c 100644 --- a/packages/react-reconciler/src/__tests__/ReactPure-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactPure-test.internal.js @@ -170,5 +170,25 @@ describe('pure', () => { expect(ReactNoop.flush()).toEqual(['Old count: 0, New count: 1', 1]); expect(ReactNoop.getChildren()).toEqual([span(1)]); }); + + it('warns for class components', () => { + class SomeClass extends React.Component { + render() { + return null; + } + } + expect(() => pure(SomeClass)).toWarnDev( + 'pure: The first argument must be a functional component.', + {withoutStack: true}, + ); + }); + + it('warns if first argument is not a function', () => { + expect(() => pure()).toWarnDev( + 'pure: The first argument must be a functional component. Instead ' + + 'received: undefined', + {withoutStack: true}, + ); + }); } }); diff --git a/packages/react/src/pure.js b/packages/react/src/pure.js index 5016c634a38f3..8acf607f3ed0a 100644 --- a/packages/react/src/pure.js +++ b/packages/react/src/pure.js @@ -17,9 +17,19 @@ export default function pure( if (typeof render !== 'function') { warningWithoutStack( false, - 'pure requires a render function but was given %s.', + 'pure: The first argument must be a functional component. Instead ' + + 'received: %s', render === null ? 'null' : typeof render, ); + } else { + const prototype = render.prototype; + if (!!(prototype && prototype.isReactComponent)) { + warningWithoutStack( + false, + 'pure: The first argument must be a functional component. Classes ' + + 'are not supported. Use React.PureComponent instead.', + ); + } } } return {