Next.js 14+Amplify v6:如何在RootLayout中获取当前用户会话?
解决Next.js 14 + AWS Amplify v6的两个核心问题
一、修复useForm导入错误
你遇到的'useForm' is not exported from 'react-hook-form'错误,本质是AWS Amplify UI React v6对react-hook-form有严格版本依赖(要求^7.43.9),如果你的项目安装了更高版本(比如v8+)就会触发这个导入失败问题。
解决步骤:
- 卸载当前版本的
react-hook-form:npm uninstall react-hook-form - 安装指定兼容版本:
npm install react-hook-form@^7.43.9 - 重启开发服务器后,Authenticator的导入错误即可消除。
二、在RootLayout中获取用户状态(用于MUI AppBar登录判断)
Next.js 14的App Router里,RootLayout默认是服务器组件,而Amplify的useAuthenticator状态钩子仅支持在客户端组件中使用,因此需要拆分组件或修改RootLayout的组件类型:
方案1:抽离AppBar为独立客户端组件(推荐)
这种方式只将需要用户状态的部分转为客户端组件,不影响整体服务器渲染性能:
- 创建
components/CustomAppBar.tsx并标记为客户端组件:'use client'; import { useAuthenticator } from '@aws-amplify/ui-react'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; export default function CustomAppBar() { const { user, signOut } = useAuthenticator(); return ( <AppBar position="static"> <Toolbar> <Typography variant="h6" sx={{ flexGrow: 1 }}> 我的应用 </Typography> {user ? ( <> <Typography variant="body1" sx={{ mr: 2 }}> {user.username} </Typography> <Button color="inherit" onClick={signOut}>退出登录</Button> </> ) : ( <Button color="inherit">登录</Button> )} </Toolbar> </AppBar> ); } - 在RootLayout中导入并使用该组件:
import CustomAppBar from '@/components/CustomAppBar'; import { Amplify } from 'aws-amplify'; import config from '@/amplifyconfiguration.json'; Amplify.configure(config); export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="zh-CN"> <body> <CustomAppBar /> {children} </body> </html> ); }
方案2:将RootLayout转为客户端组件
直接在RootLayout顶部添加客户端组件标记,即可直接使用useAuthenticator:
'use client'; import { useAuthenticator } from '@aws-amplify/ui-react'; import { Amplify } from 'aws-amplify'; import config from '@/amplifyconfiguration.json'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; Amplify.configure(config); export default function RootLayout({ children, }: { children: React.ReactNode; }) { const { user } = useAuthenticator(); return ( <html lang="zh-CN"> <body> <AppBar position="static"> <Toolbar> {/* 根据user状态渲染对应内容 */} </Toolbar> </AppBar> {children} </body> </html> ); }
注意:此方案会让整个RootLayout变为客户端组件,可能影响页面服务器渲染性能,仅在布局逻辑完全依赖客户端状态时使用。
内容的提问来源于stack exchange,提问作者Ludovic Vue
相关产品推荐
相关产品推荐

