Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
131 views
in Technique[技术] by (71.8m points)

FireBase-React Native Expo-cli,

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...