Skip to content

Commit 9090257

Browse files
authored
fix: restore execution context after RetryAfterError completed (#21766)
* test: Add failing test due to executionContext not being restored * fix: restore execution context after RetryAfterError completed * Poke codesandbox/ci * Completely restore executionContext * expect a specific error
1 parent 9fec3f2 commit 9090257

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js

+27
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,33 @@ function runActTests(label, render, unmount, rerender) {
246246
]);
247247
});
248248

249+
// @gate __DEV__
250+
it('warns if a setState is called outside of act(...) after a component threw', () => {
251+
let setValue = null;
252+
function App({defaultValue}) {
253+
if (defaultValue === undefined) {
254+
throw new Error('some error');
255+
}
256+
const [value, _setValue] = React.useState(defaultValue);
257+
setValue = _setValue;
258+
return value;
259+
}
260+
261+
expect(() => {
262+
act(() => {
263+
render(<App defaultValue={undefined} />, container);
264+
});
265+
}).toThrow('some error');
266+
267+
act(() => {
268+
rerender(<App defaultValue={0} />, container);
269+
});
270+
271+
expect(() => setValue(1)).toErrorDev([
272+
'An update to App inside a test was not wrapped in act(...).',
273+
]);
274+
});
275+
249276
describe('fake timers', () => {
250277
beforeEach(() => {
251278
jest.useFakeTimers();

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

+6
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
779779
: renderRootSync(root, lanes);
780780
if (exitStatus !== RootIncomplete) {
781781
if (exitStatus === RootErrored) {
782+
const prevExecutionContext = executionContext;
782783
executionContext |= RetryAfterError;
783784

784785
// If an error occurred during hydration,
@@ -800,6 +801,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
800801
lanes = errorRetryLanes;
801802
exitStatus = renderRootSync(root, errorRetryLanes);
802803
}
804+
805+
executionContext = prevExecutionContext;
803806
}
804807

805808
if (exitStatus === RootFatalErrored) {
@@ -972,6 +975,7 @@ function performSyncWorkOnRoot(root) {
972975

973976
let exitStatus = renderRootSync(root, lanes);
974977
if (root.tag !== LegacyRoot && exitStatus === RootErrored) {
978+
const prevExecutionContext = executionContext;
975979
executionContext |= RetryAfterError;
976980

977981
// If an error occurred during hydration,
@@ -993,6 +997,8 @@ function performSyncWorkOnRoot(root) {
993997
lanes = errorRetryLanes;
994998
exitStatus = renderRootSync(root, lanes);
995999
}
1000+
1001+
executionContext = prevExecutionContext;
9961002
}
9971003

9981004
if (exitStatus === RootFatalErrored) {

packages/react-reconciler/src/ReactFiberWorkLoop.old.js

+6
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
779779
: renderRootSync(root, lanes);
780780
if (exitStatus !== RootIncomplete) {
781781
if (exitStatus === RootErrored) {
782+
const prevExecutionContext = executionContext;
782783
executionContext |= RetryAfterError;
783784

784785
// If an error occurred during hydration,
@@ -800,6 +801,8 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
800801
lanes = errorRetryLanes;
801802
exitStatus = renderRootSync(root, errorRetryLanes);
802803
}
804+
805+
executionContext = prevExecutionContext;
803806
}
804807

805808
if (exitStatus === RootFatalErrored) {
@@ -972,6 +975,7 @@ function performSyncWorkOnRoot(root) {
972975

973976
let exitStatus = renderRootSync(root, lanes);
974977
if (root.tag !== LegacyRoot && exitStatus === RootErrored) {
978+
const prevExecutionContext = executionContext;
975979
executionContext |= RetryAfterError;
976980

977981
// If an error occurred during hydration,
@@ -993,6 +997,8 @@ function performSyncWorkOnRoot(root) {
993997
lanes = errorRetryLanes;
994998
exitStatus = renderRootSync(root, lanes);
995999
}
1000+
1001+
executionContext = prevExecutionContext;
9961002
}
9971003

9981004
if (exitStatus === RootFatalErrored) {

0 commit comments

Comments
 (0)