Next.js中使用NextAuth凭证登录时Session Provider导致页面渲染报错
Next.js中使用NextAuth凭证登录时Session Provider导致页面渲染报错
Hey Ahmed,我看了你的代码和报错信息,问题其实不在Session Provider本身,而是你把MyApp组件定义成了异步函数!React组件不能是async函数,因为异步函数会返回一个Promise对象,而React期望渲染的是React元素(或null/字符串等合法的React子节点),这就是你看到"Objects are not valid as a React child (found: [object Promise])"的核心原因。
我猜你可能是之前尝试在_app里获取服务器session时,顺手加上了async关键字,但这个写法完全不符合React组件的要求,咱们一步步来解决:
第一步:修复组件的异步问题
直接把MyApp的async关键字去掉,React组件必须是同步函数:
// 把 async function MyApp(...) 改成下面这样 function MyApp({ Component, pageProps }: AppPropsWithLayout) { // 你原来的状态、方法、useEffect逻辑都保留,不需要改动 const [currentToast, setCurrentToast] = useState< null | any | ToastNottficationtype[] >(null); // ... 其他原有代码 }
第二步:正确传递Session给SessionProvider
如果你需要在全局使用服务器端获取的session,不能在MyApp组件内部异步获取,而是通过以下两种方式:
方式1:页面级单独获取(推荐)
在需要session的页面中,用getServerSideProps异步获取session,再通过pageProps传递:
// 比如你的登录页面或首页代码 import { getServerSession } from "next-auth/next"; import { authOptions } from "../path/to/your/auth/options"; // 你的NextAuth配置 export async function getServerSideProps(context) { const session = await getServerSession(context.req, context.res, authOptions); return { props: { session }, // 把session传给页面的props }; }
这样MyApp里的pageProps.session就是已经解析好的session对象,直接传给SessionProvider就行。
方式2:全局_app中统一获取
如果要在全局所有页面都注入session,可以给MyApp添加getInitialProps方法:
import App from "next/app"; import { getServerSession } from "next-auth/next"; import { authOptions } from "../path/to/your/auth/options"; MyApp.getInitialProps = async (appContext) => { // 先获取默认的appProps const appProps = await App.getInitialProps(appContext); // 从服务器端获取session const session = await getServerSession(appContext.ctx.req, appContext.ctx.res, authOptions); // 把session合并到pageProps中 return { ...appProps, pageProps: { ...appProps.pageProps, session } }; };
额外优化建议
你的Toast状态类型定义有点混乱,建议统一成ToastNottficationtype[],避免any和空值判断的麻烦:
// 初始化空数组,而不是null const [currentToast, setCurrentToast] = useState<ToastNottficationtype[]>([]); // 修改提示方法,用函数式更新更安全 const showSuccessToast = (title: string) => { setCurrentToast(prev => [...prev, { massgesKey: title, type: "success" }]); }; const showErrorToast = (title: string) => { setCurrentToast(prev => [...prev, { massgesKey: title, type: "error" }]); }; // 渲染时也不需要复杂的空值判断 {currentToast.length > 0 && currentToast.map((notification: ToastNottficationtype, index: number) => ( <ToastNottfication key={index} massgesKey={notification.massgesKey} type={notification.type} /> )) }
备注:内容来源于stack exchange,提问作者Ahmed ibrahim
相关产品推荐
相关产品推荐

