react
react copied to clipboard
[React 19] `use()` promise from state causes "async/await is not yet supported in Client Components" error
Summary
https://stackblitz.com/edit/vitejs-vite-kbccdh?file=src%2FApp.tsx
import { use, useState } from 'react';
export default function App() {
const [p] = useState(() => new Promise((res) => setTimeout(res, 500)));
use(p);
return 'hello!';
}
Note: I do not have a parent Suspense boundary.
Actual behaviour
An error is thrown
Error: async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding
'use client'to a module that was originally written for the server.
Expected behaviour
I think this should render "hello!". If I lift the promise out of the state initialiser into the module, there is no error - React holds from rendering the app until the promise resolves.
// This works fine, even without a parent <Suspense>
const p = new Promise((res) => setTimeout(res, 500));
export default function App() {
use(p);
return 'hello!';
}
If it's expected to throw an error in this scenario, then I think the error message should be improved. It should log the error message about the component suspended without a parent suspense boundary. I do think this is inconsistent though, and in original example should just work.
Not seeing the thrown error in stackblitz nor Codesandbox: https://codesandbox.io/p/sandbox/react-use-without-suspense-boundary-mpnzw3
It never commits though. Adding a Suspense boundary fixes it.
@eps1lon that's super weird, same here. Is it expected for it to never commit? I guess that'd be a pretty weird setup to not have a single suspense boundary in your entire app, but would be good to add a warning.
The issue is also that the Promise is created during render in the state intializer. When we suspend, state is discarded so we end up re-creating the Promise when the prior one resolves. Once you hoist the Promise creation outside of the component, it commits just fine: https://codesandbox.io/p/sandbox/react-use-without-suspense-boundary-forked-799ph3?file=%2Fsrc%2Findex.js%3A5%2C32&workspaceId=ae5ed9d5-7ce3-4b4a-a32e-93bfc31fc065
Leaving this open since the error message is misleading.