diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index bcb74b6ea07f8..27eaf52666a7e 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -381,6 +381,55 @@ describe('ReactIncrementalErrorHandling', () => { expect(ReactNoop.getChildren()).toEqual([]); }); + it('retries one more time if an error occurs during a render that expires midway through the tree', () => { + function Oops() { + Scheduler.unstable_yieldValue('Oops'); + throw new Error('Oops'); + } + + function Text({text}) { + Scheduler.unstable_yieldValue(text); + return text; + } + + function App() { + return ( + <> + + + + + + + ); + } + + ReactNoop.render(); + + // Render part of the tree + expect(Scheduler).toFlushAndYieldThrough(['A', 'B']); + + // Expire the render midway through + expect(() => ReactNoop.expire(10000)).toThrow('Oops'); + + expect(Scheduler).toHaveYielded([ + // The render expired, but we shouldn't throw out the partial work. + // Finish the current level. + 'Oops', + 'C', + 'D', + + // Since the error occured during a partially concurrent render, we should + // retry one more time, synchonrously. + 'A', + 'B', + 'Oops', + 'C', + 'D', + ]); + expect(ReactNoop.getChildren()).toEqual([]); + }); + it('calls componentDidCatch multiple times for multiple errors', () => { let id = 0; class BadMount extends React.Component {