3

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

0xD1x0n
  • 686
  • 4
  • 12
  • 31

4 Answers4

14

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;
Muhammad Numan
  • 23,222
  • 6
  • 63
  • 80
  • Dear Muhammad, I get the same error without any of the above problems I export both context and provider consts, I hope You be able to check my code ``` import React, { useState } from "react"; export const LanguageContext = React.createContext(); export const LanguageProvider = ({ children }) => { const [language, setLanguage] = useState("en"); return ( {children} ); }; ``` – navidabasi Jan 23 '22 at 00:14
9

In my case I imported badly

import ThemeContext from '../contexts/theme-context';

Instead

import { ThemeContext } from '../contexts/theme-context';
Caro Pérez
  • 476
  • 4
  • 4
1

You should always check what you're exporting from your context folder

In my case I import { LocalContext } from ".././services/location/location.context";

instead of import { LocationContext } from ".././services/location/location.context";

Jokanola
  • 66
  • 5
1

Mine was: I mistakenly imported the file (languageContext.js) instead of its function {LanguageContext} so now it goes like this where I called my context.

 import {LanguageContext} from "../../Context/languageContext";

 const { language } = useContext(languageContext);
 i18n.locale = language;
Dharman
  • 30,962
  • 25
  • 85
  • 135
navidabasi
  • 161
  • 1
  • 10