[英]React Context returning undefined with useContext
我在我的应用程序中设置了上下文。 不在根部,由于某种原因它返回未定义。
我将其作为创建上下文的索引:
import React, { createContext, useContext, useReducer } from 'react'
type Action = { type: 'next' } | { type: 'back' }
type Dispatch = (action: Action) => void
type State = { step: number }
type StepProviderProps = { children: React.ReactNode }
const StepContext = createContext<{ state: State; dispatch: Dispatch } | undefined>(undefined)
const stepReducer = (state: State, action: Action) => {
switch (action.type) {
case 'next': {
return { step: state.step + 1 }
}
case 'back': {
return { step: state.step - 1 }
}
default: {
throw new Error(`Unhandled action type`)
}
}
}
const StepProvider = ({ children }: StepProviderProps) => {
const [state, dispatch] = useReducer(stepReducer, { step: 0 })
const value = { state, dispatch }
return <StepContext.Provider value={value}>{children}</StepContext.Provider>
}
const useStep = () => {
const context = useContext(StepContext)
if (context === undefined) {
throw new Error('useStep should be used within StepProvider')
} else {
return context
}
}
export { StepProvider, useStep }
然后我在这里导入它:
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'
const OnboardingScreen = () => {
const [stepper, setStepper] = useState([0, 1, 2, 3, 4, 5])
const { navigate } = useNavigation()
const { user } = useAuthContext()
const {state:{step}} = useStep()
return (
<StepProvider>
<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>
</StepProvider>
)
}
export default OnboardingScreen
我想我应该能够获取上下文的控制台日志,但我得到了上下文未定义的错误,我设置为检查上下文是否已定义。
您在与StepProvider
useStep
您不能在包装它的同一组件中使用上下文中的值。
您需要将StepProvider
包装在父组件中,然后使用它:
import { StepProvider} from './StepContext'
const ParenComponent = () => {
<StepProvider>
<OnboardingScreen/>
</StepProvider>
}
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 { useStep } from './StepContext'
const OnboardingScreen = () => {
const [stepper, setStepper] = useState([0, 1, 2, 3, 4, 5])
const { navigate } = useNavigation()
const { user } = useAuthContext()
const {state:{step}} = useStep()
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>
)
}
export default OnboardingScreen
您必须在提供程序包装的组件中使用useContext
:
<StepProvider>
<OnboardingScreen />
</StepProvider>
所以,你可以这样做:
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'
const OnboardingScreen = () => {
const [stepper, setStepper] = useState([0, 1, 2, 3, 4, 5])
const { navigate } = useNavigation()
const { user } = useAuthContext()
const {state:{step}} = useStep()
// Provider removed
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>
)
}
// Export wrapped with provider
export default () => (
<StepProvider>
<OnboardingScreen />
</StepProvider>
)
对我有用的是声明类型。 使用以下逻辑:
我的 AuthContext.tsx
...
1. interface contextValueTypes {
login: Function,
logout: Function,
isLoading: boolean,
userToken: string,
}
2. export const AuthContext = createContext<contextValueTypes>({
login: Function,
logout: Function,
isLoading: false,
userToken: "",
});
...
在我的 App.js 中
const App = () => {
const { isLoading, userToken } = useContext(AuthContext);
return (
<AuthProvider>
{userToken == null ? <AppStack /> : <AuthStack />}
</AuthProvider>
);
}
我希望这对你有帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.