diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 65bab16650151..1df6aa55bf7bf 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -2358,6 +2358,7 @@ function initSuspenseListRenderState( workInProgress.memoizedState = ({ isBackwards: isBackwards, rendering: null, + renderingStartTime: 0, last: lastContentRow, tail: tail, tailExpiration: 0, @@ -2368,6 +2369,7 @@ function initSuspenseListRenderState( // We can reuse the existing object from previous renders. renderState.isBackwards = isBackwards; renderState.rendering = null; + renderState.renderingStartTime = 0; renderState.last = lastContentRow; renderState.tail = tail; renderState.tailExpiration = 0; diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index 8f002d9f1cfaa..a610391b5f9e9 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -1114,7 +1114,10 @@ function completeWork( return null; } } else if ( - now() > renderState.tailExpiration && + // The time it took to render last row is greater than time until + // the expiration. + now() * 2 - renderState.renderingStartTime > + renderState.tailExpiration && renderExpirationTime > Never ) { // We have now passed our CPU deadline and we'll just give up further @@ -1164,12 +1167,19 @@ function completeWork( // until we just give up and show what we have so far. const TAIL_EXPIRATION_TIMEOUT_MS = 500; renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS; + // TODO: This is meant to mimic the train model or JND but this + // is a per component value. It should really be since the start + // of the total render or last commit. Consider using something like + // globalMostRecentFallbackTime. That doesn't account for being + // suspended for part of the time or when it's a new render. + // It should probably use a global start time value instead. } // Pop a row. let next = renderState.tail; renderState.rendering = next; renderState.tail = next.sibling; renderState.lastEffect = workInProgress.lastEffect; + renderState.renderingStartTime = now(); next.sibling = null; // Restore the context. diff --git a/packages/react-reconciler/src/ReactFiberSuspenseComponent.js b/packages/react-reconciler/src/ReactFiberSuspenseComponent.js index 4d29159d270cb..d988c8d1b1f77 100644 --- a/packages/react-reconciler/src/ReactFiberSuspenseComponent.js +++ b/packages/react-reconciler/src/ReactFiberSuspenseComponent.js @@ -47,6 +47,8 @@ export type SuspenseListRenderState = {| isBackwards: boolean, // The currently rendering tail row. rendering: null | Fiber, + // The absolute time when we started rendering the tail row. + renderingStartTime: number, // The last of the already rendered children. last: null | Fiber, // Remaining rows on the tail of the list. diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.internal.js index 506737b7f4f6f..16a43a6bf31c9 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.internal.js @@ -1233,8 +1233,8 @@ describe('ReactSuspenseList', () => { expect(Scheduler).toFlushAndYieldThrough(['A']); - Scheduler.unstable_advanceTime(300); - jest.advanceTimersByTime(300); + Scheduler.unstable_advanceTime(200); + jest.advanceTimersByTime(200); expect(Scheduler).toFlushAndYieldThrough(['B']); @@ -1407,8 +1407,8 @@ describe('ReactSuspenseList', () => { expect(Scheduler).toFlushAndYieldThrough(['A']); - Scheduler.unstable_advanceTime(300); - jest.advanceTimersByTime(300); + Scheduler.unstable_advanceTime(200); + jest.advanceTimersByTime(200); expect(Scheduler).toFlushAndYieldThrough(['B']); diff --git a/packages/react/src/__tests__/ReactDOMTracing-test.internal.js b/packages/react/src/__tests__/ReactDOMTracing-test.internal.js index 75e25205de18e..020b2b580a24f 100644 --- a/packages/react/src/__tests__/ReactDOMTracing-test.internal.js +++ b/packages/react/src/__tests__/ReactDOMTracing-test.internal.js @@ -561,8 +561,8 @@ describe('ReactDOMTracing', () => { expect(Scheduler).toFlushAndYieldThrough(['A']); - Scheduler.unstable_advanceTime(300); - jest.advanceTimersByTime(300); + Scheduler.unstable_advanceTime(200); + jest.advanceTimersByTime(200); expect(Scheduler).toFlushAndYieldThrough(['B']);