Reputation: 883
Is there a way to keep the component suspended on the server side and render it on the client with React 18? I tried using this pattern https://beta.reactjs.org/reference/react/Suspense#providing-a-fallback-for-server-errors-and-server-only-content. It works as expected but the problem is that if I use this pattern in multiple components the console gets filled with errors that were thrown on the server side by the component so it would remain suspended. Also later all these errors get passed to the client side
<Suspense fallback={<Loading />}>
<Chat />
</Suspense>
function Chat() {
if (typeof window === 'undefined') {
throw Error('Chat should only render on the client.');
}
// ...
}
Server-side error:
Error: Chat should only render on the client.",
"at Chat (/Users/Chat.tsx:86:19)
Client-side error:
Uncaught Error: Chat should only render on the client.
at updateDehydratedSuspenseComponent (react-dom.development.js:20662:1)
at updateSuspenseComponent (react-dom.development.js:20362:1)
at beginWork (react-dom.development.js:21624:1)
at beginWork$1 (react-dom.development.js:27426:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)
at renderRootSync (react-dom.development.js:26434:1)
at performConcurrentWorkOnRoot (react-dom.development.js:25738:1)
at workLoop (scheduler.development.js:266:1)
at flushWork (scheduler.development.js:239:1)
Is there a way to achieve the same functionality but prevent errors to appear in the console without third-party SSR libraries like Next.js? My project uses the express and react-dom/server to do the SSR.
Upvotes: 3
Views: 4237
Reputation: 1256
If you're using Next.js for SSR you can mark the component for CSR with 'use client';
at the top of the file, see these Server and Client Components docs.
Suspense is simply a fallback for asynchronous rendering but will still render on the server, as far as I know.
Workaround with useEffect
:
function Wrapper() {
const [client, setClient] = useState(false)
useEffect(() => {
setClient(true)
}, [])
if (!client) return null
return <Chat />
}
Upvotes: 0