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

React Context调用useContext返回undefined问题求助

问题原因分析

你遇到的问题核心在于组件调用useStep的时机不在StepProvider的包裹范围内。React Context的传递是基于组件树的——只有当调用useContext的组件位于对应的Provider组件的子树中时,才能获取到Context的值。

看你的OnboardingScreen代码:

const OnboardingScreen = () => {
  // 这里调用useStep的时候,StepProvider还没被渲染!
  const {state:{step}} = useStep()
  return (
    <StepProvider>
      {/* ... 子组件内容 ... */}
    </StepProvider>
  )
}

当OnboardingScreen组件开始渲染时,首先会执行顶层的useStep()调用,这时候StepProvider还没有被挂载到组件树上,当前组件不在Provider的覆盖范围内,所以useContext(StepContext)返回undefined,触发了你设置的错误。


解决方案

有两种常见的修复方式,你可以根据自己的代码结构选择:

方案1:将StepProvider提升到父组件

把StepProvider移到OnboardingScreen的上层组件(比如导航配置组件、App组件或者它的直接父组件),让OnboardingScreen本身处于Provider的包裹中:

比如在导航配置里:

// 假设这是你的导航配置文件
import { StepProvider } from './StepContext'
import OnboardingScreen from './OnboardingScreen'

const AppNavigator = () => {
  return (
    <StepProvider>
      <Stack.Navigator>
        <Stack.Screen name="Onboarding" component={OnboardingScreen} />
        {/* 其他页面 */}
      </Stack.Navigator>
    </StepProvider>
  )
}

这样修改后,OnboardingScreen在渲染时就已经处于StepProvider的子树中,调用useStep()就能正常获取Context值了。

方案2:拆分组件,让useStep在Provider的子组件中调用

如果不想改动父组件结构,可以把OnboardingScreen中需要使用Context的部分拆成一个子组件,让这个子组件被StepProvider包裹:

修改后的OnboardingScreen代码:

import { BodyText, H3, H5, H4 } from '../../typography'
import * as React from 'react'
import { Box, Icon } from '../../components'
import { useState } from 'react'
import { StyleSheet, TouchableOpacity, View } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import { useAuthContext } from '../../context/AuthProvider'
import { Enum_Userspermissionsuser_Userrole } from '../../generated/graphql'
import Start from './Start'
import stepOne from './StepOne'
import { StepProvider, useStep } from './StepContext'

// 拆分子组件,这里面调用useStep
const InnerOnboarding = () => {
  const {state:{step}} = useStep()
  const [stepper, setStepper] = useState([0, 1, 2, 3, 4, 5])
  const { navigate } = useNavigation()
  const { user } = useAuthContext()

  return (
    <Container px={5} justifyContent="flex-start" downbg hasNavbar={false}>
      <View style={{ flexDirection: 'row', justifyContent: 'space-evenly', marginTop:'12%'}}>
        {stepper.map((step, i) => (
          <Box height={5} width={50} bg="b2gpeach" borderRadius={11} key={i} />
        ))}
      </View>
      <Start />
      {console.log(step)}
    </Container>
  )
}

const OnboardingScreen = () => {
  return (
    <StepProvider>
      <InnerOnboarding />
    </StepProvider>
  )
}
export default OnboardingScreen

这样InnerOnboarding作为StepProvider的直接子组件,在渲染时处于Context的覆盖范围内,调用useStep()就能正确获取到step值了。


关键原理提醒

React Context的工作机制是向下传递:Provider组件会为它的所有子组件(包括深层子组件)提供Context值。任何调用useContext的组件必须位于Provider的子树中,否则无法获取到Context值。你的自定义hookuseStep内部调用了useContext,所以必须遵守这个规则。

内容的提问来源于stack exchange,提问作者Jude Bobinihi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:47:29