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 :
there is some mistake in your code
UserContext
but you are importing UserContext
in App.js fileuseContext
inside of Provider child componentUserContext.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;