Next.js项目添加Auth0Provider时window未定义的问题解决咨询
Next.js项目添加Auth0Provider时window未定义的问题解决咨询
嘿,我完全懂你碰到的这个问题!Next.js的服务端渲染(SSR)特性在这里给你挖了个小坑——服务端运行代码的时候根本没有浏览器里的window对象,所以你直接写window.location.origin就会报错啦。下面给你几个靠谱的解决办法:
方法一:用useEffect在客户端动态获取redirect_uri
useEffect钩子只会在客户端渲染阶段执行,这时候就能安全访问window了。我们可以用状态来存储redirect_uri,等客户端渲染完成后再赋值:
import { useEffect, useState } from 'react'; import { Auth0Provider } from '@auth0/auth0-react'; import Head from 'next/head'; // 记得导入你的其他组件和样式 export default function Home() { const [redirectUri, setRedirectUri] = useState(''); const domain = process.env.NEXT_PUBLIC_AUTH0_DOMAIN; const clientId = process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID; useEffect(() => { // 这段代码只会在浏览器环境里执行,放心访问window setRedirectUri(window.location.origin); }, []); // 确保redirectUri有值后再渲染Auth0Provider,避免初始加载的问题 if (!redirectUri) { return <div>Loading...</div>; } return ( <Auth0Provider domain={domain} clientId={clientId} authorizationParams={{ redirect_uri: redirectUri }} > <> <Head> <title>THEJackieGleason</title> <meta name="description" content="My Personal Website"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="icon" href="/favicon.ico"/> </Head> <Header/> <div className={`${styles.wrapper} z-10`}> <ThemeProvider theme={main}> <HomePage/> <Footer/> </ThemeProvider> </div> </> </Auth0Provider> ); }
方法二:把Auth0Provider封装成客户端专用组件
如果想把Auth0的逻辑和页面代码分开,可以把Auth0Provider封装成一个单独组件,然后用Next.js的动态导入功能,指定它只在客户端渲染:
第一步:创建Auth0Wrapper组件
// components/Auth0Wrapper.tsx import { Auth0Provider } from '@auth0/auth0-react'; type Auth0WrapperProps = { children: React.ReactNode; }; export default function Auth0Wrapper({ children }: Auth0WrapperProps) { const domain = process.env.NEXT_PUBLIC_AUTH0_DOMAIN; const clientId = process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID; return ( <Auth0Provider domain={domain} clientId={clientId} authorizationParams={{ redirect_uri: window.location.origin }} > {children} </Auth0Provider> ); }
第二步:在页面中动态导入这个组件
import dynamic from 'next/dynamic'; import Head from 'next/head'; // 导入你的其他组件和样式 // 动态导入,指定ssr: false,让组件只在客户端渲染 const Auth0Wrapper = dynamic(() => import('../components/Auth0Wrapper'), { ssr: false, loading: () => <div>Loading...</div> }); export default function Home() { return ( <Auth0Wrapper> <> <Head> <title>THEJackieGleason</title> <meta name="description" content="My Personal Website"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="icon" href="/favicon.ico"/> </Head> <Header/> <div className={`${styles.wrapper} z-10`}> <ThemeProvider theme={main}> <HomePage/> <Footer/> </ThemeProvider> </div> </> </Auth0Wrapper> ); }
为什么会出现这个问题?
简单来说,Next.js在构建和首次渲染时会在Node.js环境(服务端)执行你的页面组件代码,而window是浏览器特有的全局对象,服务端根本不存在这个东西,所以直接访问就会抛出ReferenceError。我们的解决思路都是让访问window的代码只在客户端环境下执行,避开服务端渲染的阶段。
备注:内容来源于stack exchange,提问作者Jackie
相关产品推荐
相关产品推荐

