diff --git a/packages/react-test-renderer/src/ReactShallowRenderer.js b/packages/react-test-renderer/src/ReactShallowRenderer.js index 09d31cb211613..6c543055ed341 100644 --- a/packages/react-test-renderer/src/ReactShallowRenderer.js +++ b/packages/react-test-renderer/src/ReactShallowRenderer.js @@ -346,7 +346,7 @@ class ReactShallowRenderer { cleanup: memoizedState.cleanup, run: inputs == null || - shouldRunEffectsBasedOnInputs(memoizedState.inputs, inputs), + !areHookInputsEqual(inputs, memoizedState.inputs), }; } } @@ -677,7 +677,10 @@ class ReactShallowRenderer { ReactCurrentDispatcher.current = prevDispatcher; } this._finishHooks(element, context); - this._callEffectsIfDesired(); + if (this._options.callEffects) { + this._callEffects(true); + this._callEffects(false); + } } } } @@ -738,15 +741,6 @@ class ReactShallowRenderer { // because DOM refs are not available. } - _callEffectsIfDesired() { - if (!this._options.callEffects) { - return; - } - - this._callEffects(true); - this._callEffects(false); - } - _callEffects(callLayoutEffects: boolean) { for ( let hook = this._firstWorkInProgressHook; @@ -911,15 +905,4 @@ function getMaskedContext(contextTypes, unmaskedContext) { return context; } -function shouldRunEffectsBasedOnInputs( - before: Array | void | null, - after: Array, -) { - if (before == null || before.length !== after.length) { - return true; - } - - return before.some((value, i) => after[i] !== value); -} - export default ReactShallowRenderer; diff --git a/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js b/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js index c4f7da88182cb..455b1cbe3294d 100644 --- a/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js @@ -280,6 +280,81 @@ describe('ReactShallowRenderer with hooks', () => { 'call effect', ]); }); + + it('should trigger effects and cleanup depending on inputs', () => { + let _setFriend; + const happenings = []; + + function SomeComponent() { + const [friend, setFriend] = React.useState('Bons'); + const [cat] = React.useState('Muskus'); + _setFriend = setFriend; + + React.useEffect( + () => { + happenings.push('call friend effect'); + return () => { + happenings.push('cleanup friend effect'); + }; + }, + [friend], + ); + + React.useEffect(() => { + happenings.push('call empty effect'); + return () => { + happenings.push('cleanup empty effect'); + }; + }); + + React.useEffect( + () => { + happenings.push('call cat effect'); + return () => { + happenings.push('cleanup cat effect'); + }; + }, + [cat], + ); + + React.useEffect( + () => { + happenings.push('call both effect'); + return () => { + happenings.push('cleanup both effect'); + }; + }, + [friend, cat], + ); + + return ( +
+ Hello {friend} with {cat} +
+ ); + } + + const shallowRenderer = createRenderer({callEffects: true}); + shallowRenderer.render(); + + expect(happenings).toEqual([ + 'call friend effect', + 'call empty effect', + 'call cat effect', + 'call both effect', + ]); + + happenings.splice(0); + _setFriend('Maryam'); + expect(happenings).toEqual([ + 'cleanup friend effect', + 'call friend effect', + 'cleanup empty effect', + 'call empty effect', + 'cleanup both effect', + 'call both effect', + ]); + }); }); it('should work with useRef', () => {