diff --git a/src/ReactShallowRenderer.js b/src/ReactShallowRenderer.js index 8d80221..131db2d 100644 --- a/src/ReactShallowRenderer.js +++ b/src/ReactShallowRenderer.js @@ -139,20 +139,18 @@ class ReactShallowRenderer { ) { const beforeState = this._newState; - if (typeof this._instance.componentWillMount === 'function') { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. - if (typeof element.type.getDerivedStateFromProps !== 'function') { - this._instance.componentWillMount(); - } - } + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( - typeof this._instance.UNSAFE_componentWillMount === 'function' && - typeof element.type.getDerivedStateFromProps !== 'function' + typeof element.type.getDerivedStateFromProps !== 'function' && + typeof this._instance.getSnapshotBeforeUpdate !== 'function' ) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. - this._instance.UNSAFE_componentWillMount(); + if (typeof this._instance.componentWillMount === 'function') { + this._instance.componentWillMount(); + } + if (typeof this._instance.UNSAFE_componentWillMount === 'function') { + this._instance.UNSAFE_componentWillMount(); + } } // setState may have been called during cWM @@ -173,20 +171,20 @@ class ReactShallowRenderer { const oldProps = this._instance.props; if (oldProps !== props) { - if (typeof this._instance.componentWillReceiveProps === 'function') { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. - if (typeof element.type.getDerivedStateFromProps !== 'function') { - this._instance.componentWillReceiveProps(props, context); - } - } + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( - typeof this._instance.UNSAFE_componentWillReceiveProps === 'function' && - typeof element.type.getDerivedStateFromProps !== 'function' + typeof element.type.getDerivedStateFromProps !== 'function' && + typeof this._instance.getSnapshotBeforeUpdate !== 'function' ) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. - this._instance.UNSAFE_componentWillReceiveProps(props, context); + if (typeof this._instance.componentWillReceiveProps === 'function') { + this._instance.componentWillReceiveProps(props, context); + } + if ( + typeof this._instance.UNSAFE_componentWillReceiveProps === 'function' + ) { + this._instance.UNSAFE_componentWillReceiveProps(props, context); + } } this._updateStateFromStaticLifecycle(props); @@ -211,20 +209,18 @@ class ReactShallowRenderer { } if (shouldUpdate) { - if (typeof this._instance.componentWillUpdate === 'function') { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. - if (typeof type.getDerivedStateFromProps !== 'function') { - this._instance.componentWillUpdate(props, state, context); - } - } + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. if ( - typeof this._instance.UNSAFE_componentWillUpdate === 'function' && - typeof type.getDerivedStateFromProps !== 'function' + typeof element.type.getDerivedStateFromProps !== 'function' && + typeof this._instance.getSnapshotBeforeUpdate !== 'function' ) { - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for any component with the new gDSFP. - this._instance.UNSAFE_componentWillUpdate(props, state, context); + if (typeof this._instance.componentWillUpdate === 'function') { + this._instance.componentWillUpdate(props, state, context); + } + if (typeof this._instance.UNSAFE_componentWillUpdate === 'function') { + this._instance.UNSAFE_componentWillUpdate(props, state, context); + } } } diff --git a/src/__tests__/ReactShallowRenderer-test.js b/src/__tests__/ReactShallowRenderer-test.js index 2c6618d..7e60bde 100644 --- a/src/__tests__/ReactShallowRenderer-test.js +++ b/src/__tests__/ReactShallowRenderer-test.js @@ -128,6 +128,48 @@ describe('ReactShallowRenderer', () => { shallowRenderer.render(); }); + it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', () => { + class Component extends React.Component { + getSnapshotBeforeUpdate() { + return null; + } + componentWillMount() { + throw Error('unexpected'); + } + componentWillReceiveProps() { + throw Error('unexpected'); + } + componentWillUpdate() { + throw Error('unexpected'); + } + render() { + return null; + } + } + + const shallowRenderer = createRenderer(); + shallowRenderer.render(); + shallowRenderer.render(); + }); + + it('should not call getSnapshotBeforeUpdate or componentDidUpdate when updating since refs wont exist', () => { + class Component extends React.Component { + getSnapshotBeforeUpdate() { + throw Error('unexpected'); + } + componentDidUpdate() { + throw Error('unexpected'); + } + render() { + return null; + } + } + + const shallowRenderer = createRenderer(); + shallowRenderer.render(); + shallowRenderer.render(); + }); + it('should only render 1 level deep', () => { function Parent() { return (