Gatsby项目中React useContext返回undefined的问题求助
React Context在Gatsby新项目中返回undefined的问题
问题场景
在Gatsby项目中使用React Context功能,复制旧项目中可正常运行的代码到新项目后,useAuth()始终返回undefined,无法获取预期的状态和方法。
新项目相关代码
context.js
import React, { useContext, useState } from "react"; const defaultState = { isLoggedIn: false, }; const AuthContext = React.createContext(); export function useAuth() { return useContext(AuthContext); } export function AuthProvider({ children }) { const [isLoggedIn, setIsLoggedIn] = useState(false); function toggle() { console.log("BOO!"); } const value = { isLoggedIn, setIsLoggedIn, }; return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; }
app.js
import React from "react"; import { Router } from "@reach/router"; import IndexPage from "./index"; import ProjectPage from "./project"; import { AuthProvider } from "../contexts/context"; const App = () => ( <AuthProvider> <Router basepath="/app"> <IndexPage path="/" component={IndexPage} /> <ProjectPage path="/project" component={ProjectPage} /> </Router> </AuthProvider> ); export default App;
index.js
import React, { useContext } from "react"; import { Link } from "gatsby"; import { useAuth } from "../contexts/context"; import { AuthContext } from "../contexts/context"; const IndexPage = () => { console.log(useAuth()) return ( <div className="w-40 h-40 bg-red-400"> {/*<Link to="/project">to projects</Link>*/} <div>Click me to toggle: uh</div> </div> ); }; export default IndexPage;
问题原因及修复方案
1. @reach/router路由写法错误
@reach/router的组件渲染不需要component属性,直接将组件作为<Router>的子元素即可。错误的写法会导致组件没有被正确挂载到AuthProvider的上下文环境中。
修复后的app.js:
import React from "react"; import { Router } from "@reach/router"; import IndexPage from "./index"; import ProjectPage from "./project"; import { AuthProvider } from "../contexts/context"; const App = () => ( <AuthProvider> <Router basepath="/app"> <IndexPage path="/" /> <ProjectPage path="/project" /> </Router> </AuthProvider> ); export default App;
2. Gatsby页面渲染逻辑导致AuthProvider未包裹目标页面
Gatsby默认会直接渲染src/pages目录下的文件作为路由页面,如果你将IndexPage放在src/pages/index.js,它会被Gatsby直接渲染,而非通过App组件的Router加载,自然无法获取到AuthProvider的上下文。
修复方案:
将AuthProvider设置为Gatsby全局根包裹组件,在gatsby-browser.js中添加以下代码:
import React from "react"; import { AuthProvider } from "./src/contexts/context"; export const wrapRootElement = ({ element }) => { return <AuthProvider>{element}</AuthProvider>; };
这样所有Gatsby页面都会被AuthProvider包裹,无论通过哪种方式渲染,都能正常访问Context内容。
额外优化
删除IndexPage中多余的AuthContext导入,只保留useAuth即可:
import React from "react"; import { Link } from "gatsby"; import { useAuth } from "../contexts/context"; const IndexPage = () => { const auth = useAuth(); console.log(auth); return ( <div className="w-40 h-40 bg-red-400"> {/*<Link to="/project">to projects</Link>*/} <div>Click me to toggle: uh</div> </div> ); }; export default IndexPage;
内容的提问来源于stack exchange,提问作者Yerin
相关产品推荐
相关产品推荐

