been stuck on this one for a while. Using Firebase for a react native project. I have used the Context Api along with useReducer to dispatch functions to update global state in my app. I have used firebase for Authentication. Basically I want to be able to Authenticate a user with Firebase then save the User Object sent by Firebsae as Global state. My issue is the state either stays null or returns undefined but console logs shows the data exists. Once I accidently tried to log in a second time after a failed first attempt and and the code works. My code is far from refined and pretty basic right now. I have looked all over the net for help for weeks now.`import { StatusBar } from 'expo-status-bar';
App Component file
import React, {useContext, useState, useEffect} from 'react';
import { StyleSheet, Text, View, LogBox, ActivityIndicator } from 'react-native';
//Navigation imports
import { NavigationContainer} from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import {createStackNavigator} from '@react-navigation/stack';
//Screen imports
import SignupScreen from './src/screens/SignupScreen';
import SigninScreen from './src/screens/SigninScreen';
import ClockingScreen from './src/screens/ClockingScreen';
import AccountScreen from './src/screens/AccountScreen';
import ManageScreen from './src/screens/ManageScreen';
//Vector Icons
import { Feather, AntDesign, Entypo } from '@expo/vector-icons';
//Context imports
import {Provider as AuthProvider} from './src/context/AuthContext';
import {Context as AuthContext} from './src/context/AuthContext';
import {firebase} from './src/firebase/config';
LogBox.ignoreLogs(['Setting a timer']);
const AuthStack = createStackNavigator();
const LoginFlow = ()=>{
return (<AuthStack.Navigator>
<AuthStack.Screen name='Signup' component={SignupScreen} options ={{headerShown:false}}/>
<AuthStack.Screen name='Signin' component={SigninScreen} options ={{headerShown:false}}/>
</AuthStack.Navigator>
)
}
const AccountStack = createStackNavigator();
const Account = ()=>{
return (<AccountStack.Navigator>
<AccountStack.Screen name='Account' component={AccountScreen} options ={{headerShown:false}}/>
</AccountStack.Navigator>
)
}
const ClockingStack = createStackNavigator();
const Clocking = ()=>{
return (<ClockingStack.Navigator>
<ClockingStack.Screen name='Clocking' component={ClockingScreen} options ={{headerShown:false}}/>
</ClockingStack.Navigator>
)
}
const ManageStack = createStackNavigator();
const Manage = ()=>{
return (<ManageStack.Navigator>
<ManageStack.Screen name='Manage' component={ManageScreen} options ={{headerShown:false}}/>
</ManageStack.Navigator>
)
}
const Tab = createBottomTabNavigator();
const EmployeeFlow = ()=> {
return (
<Tab.Navigator>
<Tab.Screen name="Clocking" component={Clocking} options ={{headerShown:false, tabBarLabel: 'TimeSheet', tabBarIcon: ({ color, size }) => (
<AntDesign name="clockcircleo" size={24} color="black" />)}} />
<Tab.Screen name="Account" component={Account} options ={{headerShown:false, tabBarLabel: 'Account', tabBarIcon: ({ color, size }) => (
<Feather name="settings" size={24} color="black" />)}} />
<Tab.Screen name="Manage" component={Manage} options ={{headerShown:false, tabBarLabel: 'Manage', tabBarIcon: ({ color, size }) => (
<Entypo name="text-document-inverted" size={24} color="black" />)}} />
</Tab.Navigator>
);
}
const Stack = createStackNavigator();
const App = ()=>{
const [loading, setLoading] = useState(true)
const [user, setUser] = useState(null)
useEffect(()=>{
const usersRef = firebase.firestore().collection('users');
firebase.auth().onAuthStateChanged(user => {
if (user) {
usersRef
.doc(user.uid)
.get()
.then((document) => {
const userData = document.data()
setLoading(false)
setUser(userData)
})
.catch((error) => {
setLoading(false)
});
} else {
setLoading(false)
}
})
}, [])
if(loading)
{
return <View style={{flex:1, justifyContent:"center", alignItems:"center"}}>
<Text style={{fontSize:25, color:'orange'}}>L...O...A...D...I...N...G...</Text>
<ActivityIndicator size="large" color="#00ff00"/>
</View>
}
return (
<NavigationContainer>
<Stack.Navigator>
{user ? ( <Stack.Screen name = "Clocking" component={EmployeeFlow} options = {{headerShown:false}}/>):
( <Stack.Screen name = "Auth" component={LoginFlow} options ={{headerShown:false}}/>)}
</Stack.Navigator>
</NavigationContainer>
);
}
export default () => {
return (
<AuthProvider>
<App/>
</AuthProvider>
)
}
Auth Context File
import createDataContext from './createDataContext';
import {firebase} from '../firebase/config';
const authReducer = (action, state)=>{
switch(action.type){
case 'sign_up':
return {...state, userData:action.payload}
break
case 'sign_in':
return {...state, userData: action.payload}
default:
return state
}
}
const signup = (dispatch) => async (email, password, name, position) =>{
try {
const response = await firebase
.auth()
.createUserWithEmailAndPassword(email, password)
const uid = response.user.uid;
const data = {
id: uid,
email,
name,
position,
};
const usersRef = firebase.firestore();
usersRef.collection('users')
.doc(uid)
.set(data)
dispatch({type:'sign_up', payload:response});
}
catch(err){
console.log(err)
}
}
const signin = (dispatch)=> async (email, password) =>{
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then((response) => {
const uid = response.user.uid
const usersRef = firebase.firestore().collection('users')
usersRef
.doc(uid)
.get()
.then(firestoreDocument => {
if (!firestoreDocument.exists) {
alert("User does not exist anymore.")
return;
}
const user = firestoreDocument.data()
})
.catch(error => {
alert(error)
});
})
.catch(error => {
alert(error)
})
}
export const {Provider, Context} = createDataContext(
authReducer,
{signup, signin},
{userData:null}
);
Signup Screen
import React, {useState, useContext} from 'react';
import {View, Text, StyleSheet, ImageBackground, TouchableOpacity} from 'react-native';
import {Input} from 'react-native-elements';
import { FontAwesome5, MaterialIcons, AntDesign, Feather } from '@expo/vector-icons';
import {Context as AuthContext} from '../context/AuthContext'
import firebase from 'firebase';
const SignupScreen = ({navigation})=>{
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [position, setPosition] = useState("");
const {signup} = useContext(AuthContext);
return <View style={styles.container}>
<ImageBackground source={require('../../assets/images/logo3.png')} style={styles.image}>
<Input
placeholder='name'
value={name}
onChangeText={(t)=>{setName(t)}}
leftIcon={<AntDesign name="user" size={24} color="black"
style={{marginLeft:5}} />} inputContainerStyle={{borderRadius:20, borderWidth:5}}/>
<Input
placeholder='position'
value={position}
onChangeText={(t)=>{setPosition(t)}}
leftIcon={<Feather name="briefcase" size={24} color="black"
style={{marginLeft:5}} />} inputContainerStyle={{borderRadius:20, borderWidth:5}}/>
<Input
placeholder='Email'
value={email}
onChangeText={(t)=>{setEmail(t)}}
leftIcon={<FontAwesome5 name="envelope" size={24} color="black"
style={{marginLeft:5}} />} inputContainerStyle={{borderRadius:20, borderWidth:5}}/>
<Input
placeholder='Password'
value={password}
onChangeText={(t)=>{setPassword(t)}}
secureTextEntry={true}
leftIcon={<MaterialIcons name="lock-outline" size={24} color="black"
style={{marginLeft:5}} />} inputContainerStyle={{borderRadius:20, borderWidth:5}}/>
<View style={{flexDirection:'row', justifyContent:'center'}}>
<TouchableOpacity onPress={()=>{signup(email, password, name, position)}} style={{...styles.button}}>
<Text style={{fontSize:20,color:'gray', fontWeight:'bold'}}>Register</Text>
</TouchableOpacity>
</View>
</ImageBackground>
<View style={{flexDirection:'row', justifyContent:'center', marginBottom:50}}>
<Text style={{fontSize:16,color:'#616967', fontWeight:'500'}}> Already have an account?</Text>
<TouchableOpacity onPress={()=>{navigation.navigate("Signin")}} >
<Text style={{fontSize:16,color:'#616967', fontWeight:'bold'}}>Sign in</Text>
</TouchableOpacity>
</View>
</View>
}
const styles = StyleSheet.create({
container :{
flex:1,
flexDirection:'column',
backgroundColor:'white'
},
image:{
flex: 1,
flexDirection:'column',
resizeMode: "cover",
justifyContent: "center",
},
button:{
height:50,
width:300,
borderRadius:60/2,
alignItems:'center',
justifyContent:'center',
borderWidth:2,
borderEndWidth:6,
borderColor:'gray',
backgroundColor:'#FDFEFE'
}
});
export default SignupScreen;
`
q