diff --git a/packages/react-dom/src/__tests__/refs-test.js b/packages/react-dom/src/__tests__/refs-test.js index 7cc764bdefdac..aaa1b0358a122 100644 --- a/packages/react-dom/src/__tests__/refs-test.js +++ b/packages/react-dom/src/__tests__/refs-test.js @@ -140,18 +140,18 @@ describe('reactiverefs', () => { expectClickLogsLengthToBe(testRefsComponent, 1); // After clicking the reset, there should still only be one click log ref. - testRefsComponent.refs.resetDiv.click(); + ReactTestUtils.act(() => testRefsComponent.refs.resetDiv.click()); expectClickLogsLengthToBe(testRefsComponent, 1); // Begin incrementing clicks (and therefore refs). - clickIncrementer.click(); + ReactTestUtils.act(() => clickIncrementer.click()); expectClickLogsLengthToBe(testRefsComponent, 2); - clickIncrementer.click(); + ReactTestUtils.act(() => clickIncrementer.click()); expectClickLogsLengthToBe(testRefsComponent, 3); // Now reset again - testRefsComponent.refs.resetDiv.click(); + ReactTestUtils.act(() => testRefsComponent.refs.resetDiv.click()); expectClickLogsLengthToBe(testRefsComponent, 1); }); }); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 85d678dec501f..dc9bdc1584c5f 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -661,6 +661,24 @@ function performConcurrentWorkOnRoot(root, didTimeout) { root !== workInProgressRoot || expirationTime !== renderExpirationTime ) { + // Before starting a fresh render, check if we can bailout on the entire tree. + // For non-root fibers, this bailout usually happens in the begin phase + // of the parent component, but roots are special because they don't + // have parents. + const remainingExpirationTimeOnRoot = + root.current.expirationTime > root.current.childExpirationTime + ? root.current.expirationTime + : root.current.childExpirationTime; + if (remainingExpirationTimeOnRoot < expirationTime) { + // We can bailout without entering the work loop. + markRootFinishedAtTime( + root, + expirationTime, + remainingExpirationTimeOnRoot, + ); + return null; + } + prepareFreshStack(root, expirationTime); startWorkOnPendingInteractions(root, expirationTime); } @@ -997,6 +1015,24 @@ function performSyncWorkOnRoot(root) { root !== workInProgressRoot || expirationTime !== renderExpirationTime ) { + // Before starting a fresh render, check if we can bailout on the entire tree. + // For non-root fibers, this bailout usually happens in the begin phase + // of the parent component, but roots are special because they don't + // have parents. + const remainingExpirationTimeOnRoot = + root.current.expirationTime > root.current.childExpirationTime + ? root.current.expirationTime + : root.current.childExpirationTime; + if (remainingExpirationTimeOnRoot < expirationTime) { + // We can bailout without entering the work loop. + markRootFinishedAtTime( + root, + expirationTime, + remainingExpirationTimeOnRoot, + ); + return null; + } + prepareFreshStack(root, expirationTime); startWorkOnPendingInteractions(root, expirationTime); }