客户端布局是否使一切都成为客户端?如果是这样,如何在保留其服务器组件的同时向其添加客户端交互性?

Chu*_*uck 7 javascript reactjs next.js

我试图了解如何使用服务器组件处理模式打开/关闭。以前,对于客户端组件,我只需将状态提升到我的Layout

export default function Layout({ children }) {

const [showPopup, setShowPopup] = useState(true)

return (
<>
  <Popup showPopup={showPopup} setShowPopup={setShowPopup} />
  <div>{children}</div>
</>
)
Run Code Online (Sandbox Code Playgroud)

然后根据这个状态显示/隐藏我的弹出窗口。但是,对于服务器组件,我不能再这样做了。为了使其工作,我需要"use client"在顶部将其设为客户端组件,但随后整个应用程序将成为客户端组件(因为这是我的根布局)。

我希望根布局成为一个服务器组件,以允许应用程序利用基础设施来实现更好的性能和整体用户体验。

那么,如何在不依赖 useState 和客户端组件的情况下处理显示或隐藏模式呢?这种情况很常见,我可能遗漏了一些明显的东西,但我找不到答案。

You*_*mar 10

如果没有客户端组件,您就无法useState进行客户端交互(例如打开模式)或特定于客户端的代码。已经说过,\n不是因为Layout被标记为客户端组件,而是由它呈现的所有内容都会被标记为客户端组件。正如您在文档中所读到的,您可以将服务器组件传递给客户端组件作为以下部分的一部分props

\n
// app/page.js\n\n// \xe2\x9c\x85 This pattern works. You can pass a Server Component\n// as a child or prop of a Client Component.\nimport ClientComponent from "./ClientComponent";\nimport ServerComponent from "./ServerComponent";\n\n// Pages are Server Components by default\nexport default function Page() {\n  return (\n    <ClientComponent>\n      <ServerComponent />\n    </ClientComponent>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

因此,由于您Layout似乎除了弹出窗口和 之外没有呈现任何其他内容children,您可以将其设为客户端组件:

\n
"use client";\n\nexport default function Layout({ children }) {\n  const [showPopup, setShowPopup] = useState(true);\n\n  return (\n    <>\n      <Popup showPopup={showPopup} setShowPopup={setShowPopup} />\n      {/* children can still be a server component */}\n      <div>{children}</div>\n    </>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果布局中有一些需要在服务器上呈现的内容,您可以将弹出窗口移动到客户端包装组件中,如下所示:

\n
"use client";\n\nimport Popup from "./Popup"\nexport default function PopupWrapper() {\n  const [showPopup, setShowPopup] = useState(true);\n\n  return <Popup showPopup={showPopup} setShowPopup={setShowPopup} />;\n}\n
Run Code Online (Sandbox Code Playgroud)\n
import PopupWrapper from "./PopupWrapper";\n\nexport default function Layout({ children }) {\n  return (\n    <>\n      <PopupWrapper />\n      <div>{children}</div>\n    </>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n