You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:10:45