NextJS 13迁移时出现Context used outside of provider错误求助
解决Next.js 13 App目录下Context使用报错「context used outside of provider.」
问题根源
- App目录组件默认是服务器组件:你的login路由页面如果未标记
'use client',会以服务器组件形式渲染,而服务器组件无法调用useContext等客户端hooks,直接调用会触发错误。 - AuthContext初始值为undefined且未处理加载状态:Provider中
auth初始为undefined,且通过useEffect异步初始化,组件首次渲染(尤其是服务器端渲染)时,useAuthContext会因context为undefined直接抛出错误。
解决方案
1. 标记登录页面为客户端组件
在app/login/page.tsx顶部添加'use client',确保它能使用React客户端hooks:
'use client'; // 登录页面其余代码
2. 在Provider中处理Auth初始化状态
修改app/provider.tsx,添加加载状态避免在auth未就绪时渲染子组件,同时确保文件顶部的'use client'存在:
'use client'; import { useState, useEffect } from 'react'; // 其他必要导入... const Provider = ({children}: { children: React.ReactNode }) => { const [auth, setAuth] = useState<Auth | undefined>(undefined); const [error, setError] = useState<Error | unknown>(undefined); const [isLoading, setIsLoading] = useState(true); // ...其他状态定义 useEffect(() => { const initAuth = async () => { try { setAuth(new Auth()); } catch (e) { setError(e); } finally { setIsLoading(false); } }; if (!auth && !error) { initAuth(); } }, []); // 加载中状态 if (isLoading) { return <div>Loading...</div>; } // 初始化失败状态 if (!auth && error) { return <div>Auth初始化失败: {error instanceof Error ? error.message : '未知错误'}</div>; } return ( <ChakraProvider theme={theme} resetCSS cssVarsRoot="body"> <ColorModeScript initialColorMode={theme.config.initialColorMode}/> <AuthContext.Provider value={auth}> <UserContext.Provider value={{user: user as User, setUser}}> <ConfigContext.Provider value={{config: config as IPCConfig, setConfig}}> <DriveContext.Provider value={{ files, setFiles, sharedFiles, setSharedFiles, folders, setFolders, sharedPrograms, setSharedPrograms, programs, setPrograms, contacts, setContacts, path, setPath, }} > {children} </DriveContext.Provider> </ConfigContext.Provider> </UserContext.Provider> </AuthContext.Provider> </ChakraProvider> ) } export default Provider;
3. 优化useAuthContext的错误逻辑
修改src/contexts/auth.ts,避免在服务器渲染或auth未初始化时直接抛出错误,让组件自行处理状态:
import {createContext, useContext} from 'react'; import Auth from 'lib/auth'; type AuthContextType = Auth | undefined; const AuthContext = createContext<AuthContextType>(undefined); const useAuthContext = (): Auth | undefined => { const context = useContext(AuthContext); // 返回上下文值,由使用组件判断是否就绪 return context; }; export { AuthContext, useAuthContext };
4. 确认Root Layout的Provider导入正确
确保app/layout.tsx中正确导入客户端组件Provider:
// app/layout.tsx import Provider from './provider'; export default function RootLayout({children}: { children: React.ReactNode }) { return ( <html lang="en"> <body> <Provider> {children} </Provider> </body> </html> ); }
内容的提问来源于stack exchange,提问作者Molaryy
相关产品推荐
相关产品推荐

