diff --git a/packages/react-art/src/__tests__/ReactART-test.js b/packages/react-art/src/__tests__/ReactART-test.js index a9e0e7486fe06..7e8b2d66ac8c4 100644 --- a/packages/react-art/src/__tests__/ReactART-test.js +++ b/packages/react-art/src/__tests__/ReactART-test.js @@ -385,7 +385,7 @@ describe('ReactART', () => { , ); - ReactNoop.flushThrough(['A']); + ReactNoop.flushThrough(__DEV__ ? ['A', 'A'] : ['A']); ReactDOM.render( @@ -400,7 +400,9 @@ describe('ReactART', () => { expect(ops).toEqual([null, 'ART']); ops = []; - expect(ReactNoop.flush()).toEqual(['B', 'C']); + expect(ReactNoop.flush()).toEqual( + __DEV__ ? ['B', 'B', 'C', 'C'] : ['B', 'C'], + ); expect(ops).toEqual(['Test']); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js index fd6292385b7f4..3d44d08057214 100644 --- a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js @@ -232,7 +232,7 @@ describe('ReactDOMRoot', () => { // Flush all async work. jest.runAllTimers(); // Root should complete without committing. - expect(ops).toEqual(['Foo']); + expect(ops).toEqual(__DEV__ ? ['Foo', 'Foo'] : ['Foo']); expect(container.textContent).toEqual(''); ops = []; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index a00b795b16dd4..c4db8696f3a9a 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -250,6 +250,20 @@ function updateForwardRef( ref, renderExpirationTime, ); + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + renderWithHooks( + current, + workInProgress, + render, + nextProps, + ref, + renderExpirationTime, + ); + } setCurrentPhase(null); } else { nextChildren = renderWithHooks( @@ -543,6 +557,20 @@ function updateFunctionComponent( context, renderExpirationTime, ); + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + renderWithHooks( + current, + workInProgress, + Component, + nextProps, + context, + renderExpirationTime, + ); + } setCurrentPhase(null); } else { nextChildren = renderWithHooks( @@ -1145,6 +1173,20 @@ function mountIndeterminateComponent( context, renderExpirationTime, ); + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + renderWithHooks( + null, + workInProgress, + Component, + props, + context, + renderExpirationTime, + ); + } } else { value = renderWithHooks( null, diff --git a/packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js b/packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js index 66ddccf894d4d..dce0c6326bfa6 100644 --- a/packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js @@ -70,7 +70,11 @@ describe('ErrorBoundaryReconciliation', () => { if (isConcurrent) { renderer.unstable_flushAll(); } - }).toWarnDev(isConcurrent ? ['invalid', 'invalid'] : ['invalid']); + }).toWarnDev( + isConcurrent + ? ['invalid', 'invalid', 'invalid', 'invalid'] + : ['invalid'], + ); const Fallback = fallbackTagName; expect(renderer).toMatchRenderedOutput(); } diff --git a/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js b/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.internal.js similarity index 97% rename from packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js rename to packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.internal.js index cf61a0c3759df..9b6b5315e8b40 100644 --- a/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.internal.js @@ -11,11 +11,14 @@ 'use strict'; let React; +let ReactFeatureFlags; let ReactTestRenderer; describe('ReactTestRendererAsync', () => { beforeEach(() => { jest.resetModules(); + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false; React = require('react'); ReactTestRenderer = require('react-test-renderer'); }); diff --git a/packages/react/src/__tests__/forwardRef-test.js b/packages/react/src/__tests__/forwardRef-test.js index 2d20c1aa2acb7..be9a500decc95 100644 --- a/packages/react/src/__tests__/forwardRef-test.js +++ b/packages/react/src/__tests__/forwardRef-test.js @@ -241,11 +241,11 @@ describe('forwardRef', () => { ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(1); + expect(renderCount).toBe(__DEV__ ? 2 : 1); ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(2); + expect(renderCount).toBe(__DEV__ ? 4 : 2); }); it('should bailout if forwardRef is wrapped in memo', () => { @@ -264,13 +264,13 @@ describe('forwardRef', () => { ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(1); + expect(renderCount).toBe(__DEV__ ? 2 : 1); expect(ref.current.type).toBe('div'); ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(1); + expect(renderCount).toBe(__DEV__ ? 2 : 1); const differentRef = React.createRef(); @@ -278,14 +278,14 @@ describe('forwardRef', () => { , ); ReactNoop.flush(); - expect(renderCount).toBe(2); + expect(renderCount).toBe(__DEV__ ? 4 : 2); expect(ref.current).toBe(null); expect(differentRef.current.type).toBe('div'); ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(3); + expect(renderCount).toBe(__DEV__ ? 6 : 3); }); it('should custom memo comparisons to compose', () => { @@ -305,19 +305,19 @@ describe('forwardRef', () => { ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(1); + expect(renderCount).toBe(__DEV__ ? 2 : 1); expect(ref.current.type).toBe('div'); // Changing either a or b rerenders ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(2); + expect(renderCount).toBe(__DEV__ ? 4 : 2); // Changing c doesn't rerender ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(2); + expect(renderCount).toBe(__DEV__ ? 4 : 2); const ComposedMemo = React.memo( RefForwardingComponent, @@ -326,29 +326,29 @@ describe('forwardRef', () => { ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(3); + expect(renderCount).toBe(__DEV__ ? 6 : 3); // Changing just b no longer updates ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(3); + expect(renderCount).toBe(__DEV__ ? 6 : 3); // Changing just a and c updates ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(4); + expect(renderCount).toBe(__DEV__ ? 8 : 4); // Changing just c does not update ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(4); + expect(renderCount).toBe(__DEV__ ? 8 : 4); // Changing ref still rerenders const differentRef = React.createRef(); ReactNoop.render(); ReactNoop.flush(); - expect(renderCount).toBe(5); + expect(renderCount).toBe(__DEV__ ? 10 : 5); expect(ref.current).toBe(null); expect(differentRef.current.type).toBe('div');