我有一条路线“/”,我想在其中使用一个钩子,即下一个身份验证中的 useSession() 钩子来获取会话。但获取会话需要时间。因此,第一次渲染始终没有会话,一旦 useSession() 挂钩返回响应,它就会重新渲染。所以我的问题是,如何避免它,以便第一个渲染已经填充了用户的会话数据?
可能的解决方案:
我不想使用服务器组件,因为我需要在页面中进行一些交互,而服务器组件不提供这些功能。
显示加载栏可能有效,但这仍然不如 NextJS 12 或之前的 getServerSideProps 好。
此外,我无法使用 NextJS 的 fetch(),因为我没有可调用的 API。我可以在服务器端使用 next-auth v5 的 auth 来获取会话,也可以在客户端使用 useSession() 。
服务器渲染是即时完成此操作的唯一选择。
Next.JS v14 建议在此类情况下使用服务器组件渲染。 关于服务器和客户端组件的 Next.JS 文档:https://nextjs.org/docs/app/building-your-application/rendering。
这个想法是:
默认情况下,Next.JS v13+ 对 React 组件使用服务器端渲染 (SSR)。可以在 React 函数内发出服务器请求:
// by default, all components are rendered on the server
export const ParentServerComponent = (props) => {
//The following call will happen only on the server
const userSession = getServerSessionFromDbOrMemory();
return <SomeComponents user={userSession} />;
}
React 将在服务器端渲染为某种形式的 HTML+JSON 并流式传输到客户端。浏览器将快速渲染准备好的 HTML+JSON。
在某些情况下,您可能需要浏览器交互,例如,更新单击行为的状态或对滚动做出反应。 对于这些情况,Next.JS 遵循 React 规范,其中每个顶部包含
'use client'
的文件将被视为客户端组件。
它只会在服务器上水合,但不会完全渲染。浏览器将解析下载的JavaSript,执行代码并最终渲染组件。它通常比服务器渲染慢得多。
'use client'
export const ClientComponent = (props) => {
// hooks should be used only inside client components
const [item, setItem] = useState(0);
useEffect(() => { }, []);
return <div>{item}</div>;
}
尽可能使用服务器渲染并制作小型客户端组件是一个很好的做法。
加载的服务器数据可以像客户端组件一样传递给服务器组件。服务器组件可以包装客户端组件。
export const ParentServerComponent = (props) => {
//The following call will happen only on the server
const userSession = getServerSessionFromDbOrMemory();
return <AnotheServerComponent user={userSession}>
<ClientComponent user={userSession} />
</AnotheServerComponent>
}