Update error message for suspending at sync priority (#23361)

Instead of adding a new Suspense boundary, the default recommendation
is to wrap the suspending update with startTransition.
This commit is contained in:
Andrew Clark 2022-02-24 21:02:06 -05:00 committed by GitHub
parent 8d0d0e9a8a
commit 3a60844a0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 19 additions and 26 deletions

View File

@ -187,7 +187,7 @@ describe('ReactDOMServerSuspense', () => {
1,
);
},
'Add a <Suspense fallback=...> component higher in the tree',
'A component suspended while responding to synchronous input.',
);
itThrowsWhenRendering(
@ -200,7 +200,7 @@ describe('ReactDOMServerSuspense', () => {
1,
);
},
'Add a <Suspense fallback=...> component higher in the tree',
'A component suspended while responding to synchronous input.',
);
}

View File

@ -78,11 +78,13 @@ function renderToStringImpl(
}
if (!readyToStream) {
// Note: This error message is the one we use on the client. It doesn't
// really make sense here. But this is the legacy server renderer, anyway.
// We're going to delete it soon.
throw new Error(
'A React component suspended while rendering, but no fallback UI was specified.\n' +
'\n' +
'Add a <Suspense fallback=...> component higher in the tree to ' +
'provide a loading indicator or placeholder to display.',
'A component suspended while responding to synchronous input. This ' +
'will cause the UI to be replaced with a loading indicator. To fix, ' +
'updates that suspend should be wrapped with startTransition.',
);
}

View File

@ -499,15 +499,11 @@ function throwException(
// This is a sync/discrete update. We treat this case like an error
// because discrete renders are expected to produce a complete tree
// synchronously to maintain consistency with external state.
// TODO: We should never call getComponentNameFromFiber in production.
// Log a warning or something to prevent us from accidentally bundling it.
const uncaughtSuspenseError = new Error(
(getComponentNameFromFiber(sourceFiber) || 'A React component') +
' suspended while rendering, but no fallback UI was specified.\n' +
'\n' +
'Add a <Suspense fallback=...> component higher in the tree to ' +
'provide a loading indicator or placeholder to display.',
'A component suspended while responding to synchronous input. This ' +
'will cause the UI to be replaced with a loading indicator. To ' +
'fix, updates that suspend should be wrapped ' +
'with startTransition.',
);
// If we're outside a transition, fall through to the regular error path.

View File

@ -499,15 +499,11 @@ function throwException(
// This is a sync/discrete update. We treat this case like an error
// because discrete renders are expected to produce a complete tree
// synchronously to maintain consistency with external state.
// TODO: We should never call getComponentNameFromFiber in production.
// Log a warning or something to prevent us from accidentally bundling it.
const uncaughtSuspenseError = new Error(
(getComponentNameFromFiber(sourceFiber) || 'A React component') +
' suspended while rendering, but no fallback UI was specified.\n' +
'\n' +
'Add a <Suspense fallback=...> component higher in the tree to ' +
'provide a loading indicator or placeholder to display.',
'A component suspended while responding to synchronous input. This ' +
'will cause the UI to be replaced with a loading indicator. To ' +
'fix, updates that suspend should be wrapped ' +
'with startTransition.',
);
// If we're outside a transition, fall through to the regular error path.

View File

@ -1011,9 +1011,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.flushSync(() => {
ReactNoop.render(<AsyncText text="Async" />);
});
}).toThrow(
'AsyncText suspended while rendering, but no fallback UI was specified.',
);
}).toThrow('A component suspended while responding to synchronous input.');
});
// @gate enableCache

View File

@ -409,5 +409,6 @@
"421": "There was an error while hydrating this Suspense boundary. Switched to client rendering.",
"422": "There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.",
"423": "This root received an early update, before anything was able hydrate. Switched the entire root to client rendering.",
"424": "Text content does not match server-rendered HTML."
"424": "Text content does not match server-rendered HTML.",
"425": "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition."
}