Next.js使用next-auth未检测到session时如何自动跳转登录页
问题原因
- 两个报错本质都是服务端渲染(SSR)阶段执行了仅客户端可用的API:
- Next.js默认会先在服务端执行一次组件代码,此时
window对象不存在,next/router也还没初始化,所以直接调用signIn()或者router.push()都会报错 - 同时你忽略了
useSession返回的loading状态,session还在加载阶段就判断session为假,提前执行跳转逻辑也会导致异常
- Next.js默认会先在服务端执行一次组件代码,此时
修复方案
方案1:用useEffect包裹跳转逻辑(仅客户端执行)
useEffect只会在客户端挂载后执行,完美避开服务端执行阶段,同时要先判断loading状态,等session加载完成再做判断,修复后代码如下:
import React, { useEffect } from "react"; import { useSession, signIn, signOut } from "next-auth/client"; import { useRouter } from 'next/router' export default function Home() { const [session, loading] = useSession(); const router = useRouter() // 跳转逻辑统一放到useEffect中,仅客户端执行 useEffect(() => { // 先等session加载完成,避免loading阶段误判 if (loading) return if (session) { console.log("session = true") router.push('/blogs') } else { console.log("session = false") // 未登录自动跳转到登录页,signIn和router.push两种写法都可以 signIn() // 或者 router.push('/api/auth/signin') } }, [session, loading, router]) // loading阶段可以加个加载提示,避免闪屏 if (loading) return <div>加载中...</div> if (session) { return ( <> Signed in as {session.user.name} <br /> <button onClick={() => signOut()}>Sign out</button> </> ); } return ( <> Not signed in <br /> <button onClick={() => signIn()}>Sign in</button> </> ); }
方案2:禁用当前页面服务端渲染
如果这个页面不需要SSR能力,可以直接用next/dynamic关闭服务端渲染,也能避免服务端执行报错:
// 页面导出逻辑修改为以下写法 import dynamic from 'next/dynamic' const Home = dynamic(() => import('./home-component'), { ssr: false }) export default Home
注意点
- 所有涉及客户端API(
window、router、signIn等)的逻辑,都不要直接写在组件的顶层同步执行代码里,要放到事件回调、useEffect这类仅客户端触发的逻辑中 - 必须判断
loading状态,避免session还在加载过程中就做登录状态判断,导致不必要的跳转闪屏
内容的提问来源于stack exchange,提问作者Burton
相关产品推荐
相关产品推荐

