component:',
);
}
@@ -689,21 +727,33 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('renders an error state if child throws in render', () => {
+ it('renders an error state if child throws in render', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -716,21 +766,33 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('renders an error state if child throws in constructor', () => {
+ it('renders an error state if child throws in constructor', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -741,21 +803,31 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenConstructor constructor [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('renders an error state if child throws in componentWillMount', () => {
+ it('renders an error state if child throws in componentWillMount', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -767,15 +839,24 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenComponentWillMount constructor',
+ 'BrokenComponentWillMount componentWillMount [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
// @gate !disableLegacyContext || !__DEV__
- it('renders an error state if context provider throws in componentWillMount', () => {
+ it('renders an error state if context provider throws in componentWillMount', async () => {
class BrokenComponentWillMountWithContext extends React.Component {
static childContextTypes = {foo: PropTypes.number};
getChildContext() {
@@ -790,18 +871,20 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
});
// @gate !disableModulePatternComponents
// @gate !disableLegacyContext
- it('renders an error state if module-style context provider throws in componentWillMount', () => {
+ it('renders an error state if module-style context provider throws in componentWillMount', async () => {
function BrokenComponentWillMountWithContext() {
return {
getChildContext() {
@@ -820,13 +903,16 @@ describe('ReactErrorBoundaries', () => {
};
const container = document.createElement('div');
- expect(() =>
- ReactDOM.render(
-
-
- ,
- container,
- ),
+ const root = ReactDOMClient.createRoot(container);
+ await expect(
+ async () =>
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ }),
).toErrorDev(
'Warning: The component appears to be a function component that ' +
'returns a class instance. ' +
@@ -839,19 +925,34 @@ describe('ReactErrorBoundaries', () => {
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
});
- it('mounts the error message if mounting fails', () => {
+ it('mounts the error message if mounting fails', async () => {
function renderError(error) {
return ;
}
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
assertLog([
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
+ 'ErrorMessage constructor',
+ 'ErrorMessage componentWillMount',
+ 'ErrorMessage render',
+ // logs for error retry
'ErrorBoundary constructor',
'ErrorBoundary componentWillMount',
'ErrorBoundary render success',
@@ -868,23 +969,25 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog([
'ErrorBoundary componentWillUnmount',
'ErrorMessage componentWillUnmount',
]);
});
- it('propagates errors on retry on mounting', () => {
+ it('propagates errors on retry on mounting', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -907,21 +1010,42 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'RetryErrorBoundary constructor',
+ 'RetryErrorBoundary componentWillMount',
+ 'RetryErrorBoundary render',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'RetryErrorBoundary static getDerivedStateFromError [!]',
+ 'RetryErrorBoundary componentWillMount',
+ 'RetryErrorBoundary render',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('propagates errors inside boundary during componentWillMount', () => {
+ it('propagates errors inside boundary during componentWillMount', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -933,23 +1057,34 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenComponentWillMountErrorBoundary constructor',
+ 'BrokenComponentWillMountErrorBoundary componentWillMount [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('propagates errors inside boundary while rendering error state', () => {
+ it('propagates errors inside boundary while rendering error state', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -969,23 +1104,41 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenRenderErrorBoundary constructor',
+ 'BrokenRenderErrorBoundary componentWillMount',
+ 'BrokenRenderErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'BrokenRenderErrorBoundary static getDerivedStateFromError',
+ 'BrokenRenderErrorBoundary componentWillMount',
+ 'BrokenRenderErrorBoundary render error [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('does not call componentWillUnmount when aborting initial mount', () => {
+ it('does not call componentWillUnmount when aborting initial mount', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -1004,14 +1157,27 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'Normal constructor',
+ 'Normal componentWillMount',
+ 'Normal render',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('resets callback refs if mounting aborts', () => {
+ it('resets callback refs if mounting aborts', async () => {
function childRef(x) {
Scheduler.log('Child ref is set to ' + x);
}
@@ -1020,13 +1186,15 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -1039,29 +1207,41 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'Error message ref is set to [object HTMLDivElement]',
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog([
'ErrorBoundary componentWillUnmount',
'Error message ref is set to null',
]);
});
- it('resets object refs if mounting aborts', () => {
+ it('resets object refs if mounting aborts', async () => {
const childRef = React.createRef();
const errorMessageRef = React.createRef();
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -1074,25 +1254,37 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillMount',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render error',
'ErrorBoundary componentDidMount',
]);
expect(errorMessageRef.current.toString()).toEqual(
'[object HTMLDivElement]',
);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
expect(errorMessageRef.current).toEqual(null);
});
- it('successfully mounts if no error occurs', () => {
+ it('successfully mounts if no error occurs', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
- Mounted successfully.
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+ Mounted successfully.
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Mounted successfully.');
assertLog([
'ErrorBoundary constructor',
@@ -1101,27 +1293,30 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidMount',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches if child throws in constructor during update', () => {
+ it('catches if child throws in constructor during update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1141,32 +1336,49 @@ describe('ReactErrorBoundaries', () => {
// Render the error message
'ErrorBoundary componentWillUpdate',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary componentWillReceiveProps',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render success',
+ 'Normal componentWillReceiveProps',
+ 'Normal componentWillUpdate',
+ 'Normal render',
+ 'Normal2 constructor',
+ 'Normal2 componentWillMount',
+ 'Normal2 render',
+ 'BrokenConstructor constructor [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render error',
'Normal componentWillUnmount',
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches if child throws in componentWillMount during update', () => {
+ it('catches if child throws in componentWillMount during update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1187,32 +1399,50 @@ describe('ReactErrorBoundaries', () => {
// Render the error message
'ErrorBoundary componentWillUpdate',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary componentWillReceiveProps',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render success',
+ 'Normal componentWillReceiveProps',
+ 'Normal componentWillUpdate',
+ 'Normal render',
+ 'Normal2 constructor',
+ 'Normal2 componentWillMount',
+ 'Normal2 render',
+ 'BrokenComponentWillMount constructor',
+ 'BrokenComponentWillMount componentWillMount [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render error',
'Normal componentWillUnmount',
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches if child throws in componentWillReceiveProps during update', () => {
+ it('catches if child throws in componentWillReceiveProps during update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1228,33 +1458,47 @@ describe('ReactErrorBoundaries', () => {
// Render the error message
'ErrorBoundary componentWillUpdate',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary componentWillReceiveProps',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render success',
+ 'Normal componentWillReceiveProps',
+ 'Normal componentWillUpdate',
+ 'Normal render',
+ 'BrokenComponentWillReceiveProps componentWillReceiveProps [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render error',
'Normal componentWillUnmount',
'BrokenComponentWillReceiveProps componentWillUnmount',
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches if child throws in componentWillUpdate during update', () => {
+ it('catches if child throws in componentWillUpdate during update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1263,10 +1507,22 @@ describe('ReactErrorBoundaries', () => {
'Normal componentWillReceiveProps',
'Normal componentWillUpdate',
'Normal render',
- // BrokenComponentWillUpdate will abort rendering:
+ // BrokenComponentWillUpdate will abort rendering:
+ 'BrokenComponentWillUpdate componentWillReceiveProps',
+ 'BrokenComponentWillUpdate componentWillUpdate [!]',
+ // Handle the error
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary componentWillReceiveProps',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render success',
+ 'Normal componentWillReceiveProps',
+ 'Normal componentWillUpdate',
+ 'Normal render',
'BrokenComponentWillUpdate componentWillReceiveProps',
'BrokenComponentWillUpdate componentWillUpdate [!]',
- // Handle the error
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillUpdate',
'ErrorBoundary render error',
@@ -1275,28 +1531,31 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches if child throws in render during update', () => {
+ it('catches if child throws in render during update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1317,15 +1576,31 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillUpdate',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary componentWillReceiveProps',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render success',
+ 'Normal componentWillReceiveProps',
+ 'Normal componentWillUpdate',
+ 'Normal render',
+ 'Normal2 constructor',
+ 'Normal2 componentWillMount',
+ 'Normal2 render',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render error',
'Normal componentWillUnmount',
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('keeps refs up-to-date during updates', () => {
+ it('keeps refs up-to-date during updates', async () => {
function child1Ref(x) {
Scheduler.log('Child1 ref is set to ' + x);
}
@@ -1337,12 +1612,14 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
assertLog([
'ErrorBoundary constructor',
'ErrorBoundary componentWillMount',
@@ -1351,14 +1628,15 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidMount',
]);
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1372,6 +1650,16 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary static getDerivedStateFromError',
'ErrorBoundary componentWillUpdate',
'ErrorBoundary render error',
+ // logs for error retry
+ 'ErrorBoundary componentWillReceiveProps',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render success',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'ErrorBoundary static getDerivedStateFromError',
+ 'ErrorBoundary componentWillUpdate',
+ 'ErrorBoundary render error',
// Update Child1 ref since Child1 has been unmounted
// Child2 ref is never set because its mounting aborted
'Child1 ref is set to null',
@@ -1379,31 +1667,34 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog([
'ErrorBoundary componentWillUnmount',
'Error message ref is set to null',
]);
});
- it('recovers from componentWillUnmount errors on update', () => {
+ it('recovers from componentWillUnmount errors on update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1437,31 +1728,34 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('recovers from nested componentWillUnmount errors on update', () => {
+ it('recovers from nested componentWillUnmount errors on update', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
-
-
- ,
- container,
- );
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1496,11 +1790,11 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('picks the right boundary when handling unmounting errors', () => {
+ it('picks the right boundary when handling unmounting errors', async () => {
function renderInnerError(error) {
return Caught an inner error: {error.message}.
;
}
@@ -1509,31 +1803,34 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
- ReactDOM.render(
-
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
-
-
- ,
- container,
- );
+ logName="OuterErrorBoundary"
+ renderError={renderOuterError}>
+
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
+ await act(async () => {
+ root.render(
- ,
- container,
- );
+ logName="OuterErrorBoundary"
+ renderError={renderOuterError}>
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an inner error: Hello.');
assertLog([
// Update outer boundary
@@ -1559,39 +1856,43 @@ describe('ReactErrorBoundaries', () => {
'InnerErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog([
'OuterErrorBoundary componentWillUnmount',
'InnerErrorBoundary componentWillUnmount',
]);
});
- it('can recover from error state', () => {
+ it('can recover from error state', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
// Error boundary doesn't retry by itself:
expect(container.textContent).toBe('Caught an error: Hello.');
// Force the success path:
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.textContent).not.toContain('Caught an error');
assertLog([
'ErrorBoundary componentWillReceiveProps',
@@ -1606,75 +1907,88 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog([
'ErrorBoundary componentWillUnmount',
'Normal componentWillUnmount',
]);
});
- it('can update multiple times in error state', () => {
+ it('can update multiple times in error state', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
- ReactDOM.render(Other screen
, container);
+ await act(async () => {
+ root.render(Other screen
);
+ });
expect(container.textContent).toBe('Other screen');
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
});
- it("doesn't get into inconsistent state during removals", () => {
+ it("doesn't get into inconsistent state during removals", async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
- ReactDOM.render(, container);
+ await act(async () => {
+ root.render();
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
Scheduler.unstable_clearLog();
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it("doesn't get into inconsistent state during additions", () => {
+ it("doesn't get into inconsistent state during additions", async () => {
const container = document.createElement('div');
- ReactDOM.render(, container);
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render();
+ });
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
Scheduler.unstable_clearLog();
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it("doesn't get into inconsistent state during reorders", () => {
+ it("doesn't get into inconsistent state during reorders", async () => {
function getAMixOfNormalAndBrokenRenderElements() {
const elements = [];
for (let i = 0; i < 100; i++) {
@@ -1704,25 +2018,32 @@ describe('ReactErrorBoundaries', () => {
let fail = false;
const container = document.createElement('div');
- ReactDOM.render(
- {getAMixOfNormalAndBrokenRenderElements()},
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+ {getAMixOfNormalAndBrokenRenderElements()}
+ ,
+ );
+ });
expect(container.textContent).not.toContain('Caught an error');
fail = true;
- ReactDOM.render(
- {getAMixOfNormalAndBrokenRenderElements()},
- container,
- );
+ await act(async () => {
+ root.render(
+
+ {getAMixOfNormalAndBrokenRenderElements()}
+ ,
+ );
+ });
expect(container.textContent).toBe('Caught an error: Hello.');
Scheduler.unstable_clearLog();
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches errors originating downstream', () => {
+ it('catches errors originating downstream', async () => {
let fail = false;
class Stateful extends React.Component {
state = {shouldThrow: false};
@@ -1738,43 +2059,38 @@ describe('ReactErrorBoundaries', () => {
let statefulInst;
const container = document.createElement('div');
- ReactDOM.render(
-
- (statefulInst = inst)} />
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+ (statefulInst = inst)} />
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
expect(() => {
fail = true;
statefulInst.forceUpdate();
}).not.toThrow();
-
- assertLog([
- 'Stateful render [!]',
- 'ErrorBoundary static getDerivedStateFromError',
- 'ErrorBoundary componentWillUpdate',
- 'ErrorBoundary render error',
- 'ErrorBoundary componentDidUpdate',
- ]);
-
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches errors in componentDidMount', () => {
+ it('catches errors in componentDidMount', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+
+
+ ,
+ );
+ });
assertLog([
'ErrorBoundary constructor',
'ErrorBoundary componentWillMount',
@@ -1817,26 +2133,29 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('catches errors in componentDidUpdate', () => {
+ it('catches errors in componentDidUpdate', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
assertLog([
'ErrorBoundary componentWillReceiveProps',
'ErrorBoundary componentWillUpdate',
@@ -1855,33 +2174,29 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
it('catches errors in useEffect', async () => {
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
await act(() => {
- ReactDOM.render(
+ root.render(
Initial value
,
- container,
);
- assertLog([
- 'ErrorBoundary constructor',
- 'ErrorBoundary componentWillMount',
- 'ErrorBoundary render success',
- 'BrokenUseEffect render',
- 'ErrorBoundary componentDidMount',
- ]);
-
- expect(container.firstChild.textContent).toBe('Initial value');
- Scheduler.unstable_clearLog();
});
// verify flushed passive effects and handle the error
assertLog([
+ // logs for error retry
+ 'ErrorBoundary constructor',
+ 'ErrorBoundary componentWillMount',
+ 'ErrorBoundary render success',
+ 'BrokenUseEffect render',
+ 'ErrorBoundary componentDidMount',
'BrokenUseEffect useEffect [!]',
// Handle the error
'ErrorBoundary static getDerivedStateFromError',
@@ -1889,18 +2204,19 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary render error',
'ErrorBoundary componentDidUpdate',
]);
-
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
});
- it('catches errors in useLayoutEffect', () => {
+ it('catches errors in useLayoutEffect', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
- Initial value
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+ Initial value
+ ,
+ );
+ });
assertLog([
'ErrorBoundary constructor',
'ErrorBoundary componentWillMount',
@@ -1920,18 +2236,20 @@ describe('ReactErrorBoundaries', () => {
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
});
- it('propagates errors inside boundary during componentDidMount', () => {
+ it('propagates errors inside boundary during componentDidMount', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
- (
- We should never catch our own error: {error.message}.
- )}
- />
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+ (
+ We should never catch our own error: {error.message}.
+ )}
+ />
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
assertLog([
'ErrorBoundary constructor',
@@ -1952,11 +2270,11 @@ describe('ReactErrorBoundaries', () => {
'ErrorBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog(['ErrorBoundary componentWillUnmount']);
});
- it('calls static getDerivedStateFromError for each error that is captured', () => {
+ it('calls static getDerivedStateFromError for each error that is captured', async () => {
function renderUnmountError(error) {
return Caught an unmounting error: {error.message}.
;
}
@@ -1965,40 +2283,43 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
-
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+
+
+
+
+
+ ,
+ );
+ });
Scheduler.unstable_clearLog();
- ReactDOM.render(
-
-
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe(
'Caught an unmounting error: E2.' + 'Caught an updating error: E4.',
@@ -2048,7 +2369,7 @@ describe('ReactErrorBoundaries', () => {
'InnerUpdateBoundary componentDidUpdate',
]);
- ReactDOM.unmountComponentAtNode(container);
+ root.unmount();
assertLog([
'OuterErrorBoundary componentWillUnmount',
'InnerUnmountBoundary componentWillUnmount',
@@ -2056,7 +2377,7 @@ describe('ReactErrorBoundaries', () => {
]);
});
- it('discards a bad root if the root component fails', () => {
+ it('discards a bad root if the root component fails', async () => {
const X = null;
const Y = undefined;
let err1;
@@ -2064,7 +2385,13 @@ describe('ReactErrorBoundaries', () => {
try {
const container = document.createElement('div');
- expect(() => ReactDOM.render(, container)).toErrorDev(
+ const root = ReactDOMClient.createRoot(container);
+ await expect(
+ async () =>
+ await act(async () => {
+ root.render(, container);
+ }),
+ ).toErrorDev(
'React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function ' +
'(for composite components) but got: null.',
@@ -2074,7 +2401,13 @@ describe('ReactErrorBoundaries', () => {
}
try {
const container = document.createElement('div');
- expect(() => ReactDOM.render(, container)).toErrorDev(
+ const root = ReactDOMClient.createRoot(container);
+ await expect(
+ async () =>
+ await act(async () => {
+ root.render(, container);
+ }),
+ ).toErrorDev(
'React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function ' +
'(for composite components) but got: undefined.',
@@ -2087,19 +2420,23 @@ describe('ReactErrorBoundaries', () => {
expect(err2.message).toMatch(/got: undefined/);
});
- it('renders empty output if error boundary does not handle the error', () => {
+ it('renders empty output if error boundary does not handle the error', async () => {
const container = document.createElement('div');
- expect(() =>
- ReactDOM.render(
-
- Sibling
-
-
-
-
,
- container,
- ),
- ).toThrow('Hello');
+ const root = ReactDOMClient.createRoot(container);
+
+ await expect(async () => {
+ await act(async () => {
+ root.render(
+
+ Sibling
+
+
+
+
,
+ );
+ });
+ }).rejects.toThrow('Hello');
+
expect(container.innerHTML).toBe('');
assertLog([
'NoopErrorBoundary constructor',
@@ -2114,10 +2451,22 @@ describe('ReactErrorBoundaries', () => {
'BrokenRender constructor',
'BrokenRender componentWillMount',
'BrokenRender render [!]',
+ // logs for error retry
+ 'NoopErrorBoundary constructor',
+ 'NoopErrorBoundary componentWillMount',
+ 'NoopErrorBoundary render',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
+ 'NoopErrorBoundary static getDerivedStateFromError',
+ 'NoopErrorBoundary render',
+ 'BrokenRender constructor',
+ 'BrokenRender componentWillMount',
+ 'BrokenRender render [!]',
]);
});
- it('passes first error when two errors happen in commit', () => {
+ it('passes first error when two errors happen in commit', async () => {
const errors = [];
let caughtError;
class Parent extends React.Component {
@@ -2140,10 +2489,13 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
try {
// Here, we test the behavior where there is no error boundary and we
// delegate to the host root.
- ReactDOM.render(, container);
+ await act(async () => {
+ root.render();
+ });
} catch (e) {
if (e.message !== 'parent sad' && e.message !== 'child sad') {
throw e;
@@ -2156,19 +2508,22 @@ describe('ReactErrorBoundaries', () => {
expect(caughtError.message).toBe('child sad');
});
- it('propagates uncaught error inside unbatched initial mount', () => {
+ it('propagates uncaught error inside unbatched initial mount', async () => {
function Foo() {
throw new Error('foo error');
}
const container = document.createElement('div');
- expect(() => {
- ReactDOM.unstable_batchedUpdates(() => {
- ReactDOM.render(, container);
+ const root = ReactDOMClient.createRoot(container);
+ await expect(async () => {
+ await ReactDOM.unstable_batchedUpdates(async () => {
+ await act(async () => {
+ root.render();
+ });
});
- }).toThrow('foo error');
+ }).rejects.toThrow('foo error');
});
- it('handles errors that occur in before-mutation commit hook', () => {
+ it('handles errors that occur in before-mutation commit hook', async () => {
const errors = [];
let caughtError;
class Parent extends React.Component {
@@ -2193,9 +2548,14 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
- ReactDOM.render(, container);
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render();
+ });
try {
- ReactDOM.render(, container);
+ await act(async () => {
+ root.render();
+ });
} catch (e) {
if (e.message !== 'parent sad' && e.message !== 'child sad') {
throw e;
@@ -2208,7 +2568,7 @@ describe('ReactErrorBoundaries', () => {
expect(caughtError.message).toBe('child sad');
});
- it('should warn if an error boundary with only componentDidCatch does not update state', () => {
+ it('should warn if an error boundary with only componentDidCatch does not update state', async () => {
class InvalidErrorBoundary extends React.Component {
componentDidCatch(error, info) {
// This component does not define getDerivedStateFromError().
@@ -2225,13 +2585,15 @@ describe('ReactErrorBoundaries', () => {
};
const container = document.createElement('div');
- expect(() => {
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await expect(async () => {
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
}).toErrorDev(
'InvalidErrorBoundary: Error boundaries should implement getDerivedStateFromError(). ' +
'In that method, return a state update to display an error message or fallback UI.',
@@ -2239,7 +2601,7 @@ describe('ReactErrorBoundaries', () => {
expect(container.textContent).toBe('');
});
- it('should call both componentDidCatch and getDerivedStateFromError if both exist on a component', () => {
+ it('should call both componentDidCatch and getDerivedStateFromError if both exist on a component', async () => {
let componentDidCatchError, getDerivedStateFromErrorError;
class ErrorBoundaryWithBothMethods extends React.Component {
state = {error: null};
@@ -2261,34 +2623,39 @@ describe('ReactErrorBoundaries', () => {
};
const container = document.createElement('div');
- ReactDOM.render(
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
expect(container.textContent).toBe('ErrorBoundary');
expect(componentDidCatchError).toBe(thrownError);
expect(getDerivedStateFromErrorError).toBe(thrownError);
});
- it('should catch errors from invariants in completion phase', () => {
+ it('should catch errors from invariants in completion phase', async () => {
const container = document.createElement('div');
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toContain(
'Caught an error: input is a void element tag',
);
});
- it('should catch errors from errors in the throw phase from boundaries', () => {
+ it('should catch errors from errors in the throw phase from boundaries', async () => {
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
const thrownError = new Error('original error');
const Throws = () => {
@@ -2304,22 +2671,24 @@ describe('ReactErrorBoundaries', () => {
}
}
- ReactDOM.render(
-
-
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
expect(container.textContent).toContain(
'Caught an error: gotta catch em all',
);
});
- it('should protect errors from errors in the stack generation', () => {
+ it('should protect errors from errors in the stack generation', async () => {
const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
const evilError = {
message: 'gotta catch em all',
@@ -2340,19 +2709,22 @@ describe('ReactErrorBoundaries', () => {
return ;
}
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await expect(async () => {
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
+ }).rejects.toThrow('gotta catch em all');
expect(container.textContent).toContain(
'Caught an error: gotta catch em all.',
);
});
- it('catches errors thrown in componentWillUnmount', () => {
+ it('catches errors thrown in componentWillUnmount', async () => {
class LocalErrorBoundary extends React.Component {
state = {error: null};
static getDerivedStateFromError(error) {
@@ -2392,16 +2764,18 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
-
- ReactDOM.render(
-
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+
+ await act(async () => {
+ root.render(
+
+
+
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('sibling');
expect(container.lastChild.textContent).toBe('broken');
@@ -2412,12 +2786,13 @@ describe('ReactErrorBoundaries', () => {
'BrokenComponentWillUnmount render',
]);
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
// React should skip over the unmounting boundary and find the nearest still-mounted boundary.
expect(container.firstChild.textContent).toBe('OuterFallback');
@@ -2432,7 +2807,7 @@ describe('ReactErrorBoundaries', () => {
]);
});
- it('catches errors thrown while detaching refs', () => {
+ it('catches errors thrown while detaching refs', async () => {
class LocalErrorBoundary extends React.Component {
state = {error: null};
static getDerivedStateFromError(error) {
@@ -2474,16 +2849,18 @@ describe('ReactErrorBoundaries', () => {
}
const container = document.createElement('div');
-
- ReactDOM.render(
-
-
-
-
-
- ,
- container,
- );
+ const root = ReactDOMClient.createRoot(container);
+
+ await act(async () => {
+ root.render(
+
+
+
+
+
+ ,
+ );
+ });
expect(container.firstChild.textContent).toBe('sibling');
expect(container.lastChild.textContent).toBe('ref');
@@ -2495,12 +2872,13 @@ describe('ReactErrorBoundaries', () => {
'LocalBrokenCallbackRef ref true',
]);
- ReactDOM.render(
-
-
- ,
- container,
- );
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
// React should skip over the unmounting boundary and find the nearest still-mounted boundary.
expect(container.firstChild.textContent).toBe('OuterFallback');