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

使用React ContextAPI+useState获取themeMode返回undefined问题求助

问题根源

你在App组件的顶层直接调用了useToggleTheme(),但此时App组件并没有被ToggleThemeContextProvider包裹——React Context的作用域仅限于Provider所包裹的子组件树,Provider外部的组件只能获取到createContext时传入的默认值。你这里用{} as ITheme强制转换了一个空对象作为默认值,所以themeMode自然是undefined。

解决方案

把需要使用themeMode的逻辑移到ToggleThemeContextProvider内部的组件中,比如抽离一个内部组件:

export default function App() {
  return (
    <HeaderContextProvider>
      <ToggleThemeContextProvider>
        <AppContent />
      </ToggleThemeContextProvider>
    </HeaderContextProvider>
  )
}

// 单独抽离内部组件,确保在ToggleThemeContextProvider作用域内
function AppContent() {
  const { themeMode } = useToggleTheme()
  console.log(themeMode) // 现在能正常获取到主题值了

  return (
    <ThemeProvider theme={themeMode}>
      <SafeAreaProvider>
        {fontsLoaded ? <Routes /> : <Loading />}
        <StatusBar style="auto" backgroundColor="transparent" translucent />
      </SafeAreaProvider>
    </ThemeProvider>
  )
}
关于initialValues的问题说明

你之前把initialValues传入createContext后setThemeMode失效,是因为默认值里的setThemeMode是个空函数() => null——当组件不在Provider内部时,拿到的是这个默认的空函数,自然无法触发状态更新。只有在Provider包裹的子组件中,才能获取到Provider提供的真实setThemeMode方法。

额外优化建议

可以在自定义hook里添加校验,防止在Provider外部调用时出现隐性错误:

export function useToggleTheme(): ITheme {
  const context = useContext(ToggleThemeContext)
  if (!context) {
    throw new Error('useToggleTheme must be used within a ToggleThemeContextProvider')
  }
  return context
}

这样错误使用时会抛出明确的提示,更容易排查问题。

关于另一个布尔值Context的问题

和当前主题Context的问题完全一致:调用useXXX hook的组件不在对应的Provider作用域内,所以拿到的是默认值(如果默认值未正确初始化就是undefined);而能调用setXXX更新状态的组件,一定是在Provider内部的,所以状态能正常更新,但外部组件还是拿不到最新值。

内容的提问来源于stack exchange,提问作者Vinicius Celestino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:50:44