Bug: putting promise into JSX will cause hydration issue
React version: 18.3.0-canary-5dd35968b-20231201
Steps To Reproduce
- clone https://github.com/himself65/react-hydration-error
- pnpm install && pnpm run dev
Link to code example:
import { Component } from '@/components/component'
export default function Home () {
const delayedMessage = new Promise((resolve) => {
setTimeout(() => resolve('Hello from server!'), 2000)
})
return (
<main>
<div>
<Component delayedMessage={delayedMessage}/>
</div>
</main>
)
}
"use client"
export function Component ({
delayedMessage
}) {
return (
<div>
{delayedMessage}
</div>
)
}
The current behavior
The expected behavior
Won't have hydration error
Related downstream repo: https://github.com/dai-shi/waku/pull/203
https://github.com/dai-shi/waku/issues/202
I think this is a React issue, not next.js. Since our customized react framework has the same error
~~Prop values passed from a Server Component to Client Component must be serializable.~~
~~https://react.dev/reference/react/use-client~~
~~I think using async/await works well.~~
Sorry, Promise is serealizable. I misunderstood.
Values of serialized promises are different between client side and server side.
The issue can be resolved by using useEffect hook . Head to next js documentation.
- https://nextjs.org/docs/messages/react-hydration-error
I found a workaround for this matter. It is to use use to Promises.
https://github.com/NakZMichael/react-hydration-error
However, looking at the following PR, it appears that this workaround is not supposed to be necessary. https://github.com/facebook/react/pull/25634
And it seems to be related to the following Issue discussed in the Next.js repository. https://github.com/vercel/next.js/issues/56470
Since promise is a valid jsx element, I think it should not cause ssr issues or otherwise should be documented
@himself65 , Thanks for reporting the hydration issue with promises in JSX. Putting promises directly in JSX can be tricky in React 18. Here's a quick fix:
Render a placeholder on the server while the promise resolves on the client (e.g., a loading spinner). Update the DOM with the resolved value once it's available. Remember to update the server-side HTML with the resolved value for optimal performance.
For more advanced handling, consider Suspense or data fetching libraries like react-query or SWR.
Happy coding!
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
bump
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!