From fd47129ce6e8af37004686262bd27fa787af37fc Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 3 Nov 2017 16:16:56 +0000 Subject: [PATCH] Remove support for passing badly typed elements to shallow renderer (#11442) --- .../src/ReactShallowRenderer.js | 19 ++++++---- .../__tests__/ReactShallowRenderer-test.js | 38 +++++++++++++++++-- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/packages/react-test-renderer/src/ReactShallowRenderer.js b/packages/react-test-renderer/src/ReactShallowRenderer.js index 8f64bef8e0..28af0edb36 100644 --- a/packages/react-test-renderer/src/ReactShallowRenderer.js +++ b/packages/react-test-renderer/src/ReactShallowRenderer.js @@ -47,6 +47,7 @@ class ReactShallowRenderer { 'it by passing it to React.createElement.' : '', ); + // Show a special message for host elements since it's a common case. invariant( typeof element.type !== 'string', 'ReactShallowRenderer render(): Shallow rendering works only with custom ' + @@ -54,6 +55,14 @@ class ReactShallowRenderer { 'inspecting the rendered output, look at `el.props` directly instead.', element.type, ); + invariant( + typeof element.type === 'function', + 'ReactShallowRenderer render(): Shallow rendering works only with custom ' + + 'components, but the provided element type was `%s`.', + Array.isArray(element.type) + ? 'array' + : element.type === null ? 'null' : typeof element.type, + ); if (this._rendering) { return; @@ -144,12 +153,8 @@ class ReactShallowRenderer { ) { this._instance.componentWillReceiveProps(props, context); } - // Read state after cWRP in case it calls setState - // Fallback to previous instance state to support rendering React.cloneElement() - // TODO: the cloneElement() use case is broken and should be removed - // https://github.com/facebook/react/issues/11441 - const state = this._newState || this._instance.state || emptyObject; + const state = this._newState || oldState; let shouldUpdate = true; if (this._forcedUpdate) { @@ -161,9 +166,7 @@ class ReactShallowRenderer { state, context, ); - } else if (type && type.prototype && type.prototype.isPureReactComponent) { - // TODO: we can remove the type existence check when we fix this: - // https://github.com/facebook/react/issues/11441 + } else if (type.prototype && type.prototype.isPureReactComponent) { shouldUpdate = !shallowEqual(oldProps, props) || !shallowEqual(oldState, state); } diff --git a/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js b/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js index 7bd5cf159c..f7aa3168f4 100644 --- a/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js @@ -844,12 +844,44 @@ describe('ReactShallowRenderer', () => { } const shallowRenderer = createRenderer(); - let result = shallowRenderer.render(); + const el = ; + let result = shallowRenderer.render(el); expect(result).toEqual(
foo:bar
); - const instance = shallowRenderer.getMountedInstance(); - const cloned = React.cloneElement(instance, {foo: 'baz'}); + const cloned = React.cloneElement(el, {foo: 'baz'}); result = shallowRenderer.render(cloned); expect(result).toEqual(
baz:bar
); }); + + it('throws usefully when rendering badly-typed elements', () => { + spyOn(console, 'error'); + const shallowRenderer = createRenderer(); + + var Undef = undefined; + expect(() => shallowRenderer.render()).toThrowError( + 'ReactShallowRenderer render(): Shallow rendering works only with custom ' + + 'components, but the provided element type was `undefined`.', + ); + + var Null = null; + expect(() => shallowRenderer.render()).toThrowError( + 'ReactShallowRenderer render(): Shallow rendering works only with custom ' + + 'components, but the provided element type was `null`.', + ); + + var Arr = []; + expect(() => shallowRenderer.render()).toThrowError( + 'ReactShallowRenderer render(): Shallow rendering works only with custom ' + + 'components, but the provided element type was `array`.', + ); + + var Obj = {}; + expect(() => shallowRenderer.render()).toThrowError( + 'ReactShallowRenderer render(): Shallow rendering works only with custom ' + + 'components, but the provided element type was `object`.', + ); + + // One warning for each element creation + expectDev(console.error.calls.count()).toBe(4); + }); });