diff --git a/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js index 327b83b940235..1611b904bef1a 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js @@ -187,7 +187,7 @@ describe('ReactDOMServerSuspense', () => { 1, ); }, - 'Add a component higher in the tree', + 'A component suspended while responding to synchronous input.', ); itThrowsWhenRendering( @@ -200,7 +200,7 @@ describe('ReactDOMServerSuspense', () => { 1, ); }, - 'Add a component higher in the tree', + 'A component suspended while responding to synchronous input.', ); } diff --git a/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js b/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js index 338c77de436d7..1a11911ad5317 100644 --- a/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js +++ b/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js @@ -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 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.', ); } diff --git a/packages/react-reconciler/src/ReactFiberThrow.new.js b/packages/react-reconciler/src/ReactFiberThrow.new.js index 24eb0a590b1b3..cc5e3215c786d 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.new.js +++ b/packages/react-reconciler/src/ReactFiberThrow.new.js @@ -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 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. diff --git a/packages/react-reconciler/src/ReactFiberThrow.old.js b/packages/react-reconciler/src/ReactFiberThrow.old.js index 5a3c720e1cc58..727c613d7622f 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.old.js +++ b/packages/react-reconciler/src/ReactFiberThrow.old.js @@ -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 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. diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js index 751caed68edeb..dc2d57d225a4d 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js @@ -1011,9 +1011,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); - }).toThrow( - 'AsyncText suspended while rendering, but no fallback UI was specified.', - ); + }).toThrow('A component suspended while responding to synchronous input.'); }); // @gate enableCache diff --git a/scripts/error-codes/codes.json b/scripts/error-codes/codes.json index dafa574903496..367b736931cfc 100644 --- a/scripts/error-codes/codes.json +++ b/scripts/error-codes/codes.json @@ -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." }