简体   繁体   中英

How can I suspend component on the server side but render it on the client side?

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.

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 />
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM