Search code examples
react-nativeexporeact-context

undefined is not an object (evaluating 'Context._context') - React Native


I am trying to wrap one of my navigators with User Context that I created. I have achieved this before in other projects but I am encountering an issue. I Tried following this solution but it doesn't seem to be the same issue I am encountering. I can't exactly tell what is wrong here.

App.js Code :

import React, { useContext, useEffect } from "react";
import { View, Text, AsyncStorage, Button } from "react-native";
import { createStackNavigator } from "@react-navigation/stack";
import HomeScreen from "./src/screens/HomeScreen";
import LoginScreen from "./src/screens/login";
import CalendarScreen from "./src/screens/Calendar";
import SignUpScreen from "./src/screens/signUp";
import { scale, vs } from "react-native-size-matters";
import { createDrawerNavigator } from "@react-navigation/drawer";
import { createMaterialBottomTabNavigator } from "@react-navigation/material-bottom-tabs";
import { Icon } from "react-native-elements";
import UserContext, { UserProvider } from "./src/screens/Context/UserContext";
import { NavigationContainer } from "@react-navigation/native";

const Tab = createMaterialBottomTabNavigator();
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();

const signedIn = true; //this is for testing
const drawer_style = {
  backgroundColor: "#202B35",
  activeTintColor: "#000",

  width: 200,
};

const drawer_item_style = {
  activeTintColor: "orange",
  inactiveTintColor: "#fff",

  itemStyle: { marginVertical: vs(10) },
};

const non_user_stack = () => {
  <Stack.Navigator>
    <Stack.Screen
      name="Sign in - Cal "
      component={LoginScreen}
      options={({ navigation }) => ({
        headerShown: true,
        headerTintColor: "orange",

        headerStyle: {
          backgroundColor: "#202B35",
        },
      })}
    />

    <Stack.Screen
      name="Sign up - Cal "
      component={SignUpScreen}
      options={({ navigation }) => ({
        headerShown: true,
        headerTintColor: "orange",

        headerStyle: {
          backgroundColor: "#202B35",
        },
      })}
    />
  </Stack.Navigator>;
};

const UserMenu = () => {
  return (
    <NavigationContainer>
      <Drawer.Navigator
        initialRouteName="Home"
        drawerStyle={drawer_style}
        drawerContentOptions={drawer_item_style}
        drawerType="front"
      >
        <Drawer.Screen name="Home" component={MyStack} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
};
const MyStack = () => {

  return(

    <Stack.Navigator>
      <Stack.Screen
        name="Cal"
        component={BottomNav}
        options={({ navigation }) => ({
          headerShown: true,
          headerTintColor: "orange",

          headerStyle: {
            backgroundColor: "#202B35",
          },
          headerLeft: (props) => (
            <Icon
              size={25}
              name={"ios-menu"}
              iconStyle={{
                fontSize: scale(30),
                color: "orange",
                margin: 5,
                marginLeft: 10,
              }}
              type="ionicon"
              color="orange"
              onPress={() => {
                navigation.toggleDrawer();
              }}
            />
          ),
        })}
      />
    </Stack.Navigator>
  ) 
};


export default App = () => {

  const { isSignedIn, check_and_set_signin_status } = useContext(UserContext); //<-- causes crash

  return (
      isSignedIn === "false" ? (
       <UserProvider>
         <UserMenu />
       </UserProvider>
    ) : (
      <non_user_stack></non_user_stack>
    );
  );

};

UserContext.js :

import React, { useState, useEffect } from "react";
import * as Permissions from "expo-permissions";
import axios from "axios";
import { AsyncStorage } from "react-native";
//import registerForPushNotificationsAsync from "../Hooks/registerForPushNotifications";
import Constants from "expo-constants";

const UserContext = React.createContext();

const IS_SIGNEDIN = "is_signed_in";

export const UserProvider = ({ children }) => {
  const [isSignedIn, setSignIn] = useState(null);
  const [didAuthenticate, setAuthenticated] = useState(null);

  //Check if this user already signed in before and didnt log out since their last session
  //used for conditional rendering
  const check_and_set_signin_status = async () => {
    const signed_in = await AsyncStorage.getItem(IS_SIGNEDIN);

    if (signed_in == null || signed_in == "false") {
      await AsyncStorage.setItem(IS_SIGNEDIN, "false");
      setSignIn("false");
    } else {
      setSignIn("true");
    }

  };


  return (
    <UserContext.Provider
      value={{
        isSignedIn, // well use this for conditional rendering

        check_and_set_signin_status,
      }}
    >
      {children}
    </UserContext.Provider>
  );
};

The Error :

enter image description here


Solution

  • there is some mistake in your code

    1. you are not exporting UserContext but you are importing UserContext in App.js file
    2. you are trying to use useContext and provider in same file but you have to useContext inside of Provider child component
    3. you are non_user_stack with first letter capital but you have to make first letter capital

    UserContext.js : you have to export UserContext in this file

    import React, { useState, useEffect } from "react";
    import { Text } from 'react-native'
    import * as Permissions from "expo-permissions";
    import axios from "axios";
    import { AsyncStorage } from "react-native";
    //import registerForPushNotificationsAsync from "../Hooks/registerForPushNotifications";
    import Constants from "expo-constants";
    
    const UserContext = React.createContext();
    export default UserContext;
    const IS_SIGNEDIN = "is_signed_in";
    
    export const UserProvider = ({ children }) => {
      const [isSignedIn, setSignIn] = useState(null);
      const [didAuthenticate, setAuthenticated] = useState(null);
      const check_and_set_signin_status = async () => {
        const signed_in = await AsyncStorage.getItem(IS_SIGNEDIN);
    
        if (signed_in == null || signed_in == "false") {
          await AsyncStorage.setItem(IS_SIGNEDIN, "false");
          setSignIn("false");
        } else {
          setSignIn("true");
        }
    
      };
    
    
      return (
        <UserContext.Provider
          value={{
            isSignedIn, // well use this for conditional rendering
    
            check_and_set_signin_status,
          }}
        >
          {children}
        </UserContext.Provider>
      );
    };
    

    App.js Code :

    const App = () => {
     const { isSignedIn, check_and_set_signin_status } = useContext(UserContext); //<-- causes crash
      console.log( isSignedIn, check_and_set_signin_status ,"useContext")
      return isSignedIn === "false" ? (
        <UserMenu />
      ) : (
        <Non_user_stack></Non_user_stack>
      );
    };
    
    const jsx = () => (
      <UserProvider>
        <App />
      </UserProvider>
    );
    
    export default jsx;