After implementing a component that handles User Registration in Parse in the last guide, you will now learn how to log in and log out users using the same Parse.User class. You will also learn to install and configure react-navigation so you can navigate the user through your new screens and components.
The Parse.User.logIn method stores in your local storage a valid user session, so future calls to methods like currentAsync will successfully retrieve your User data. On the other hand, logOut will clear this session from disk and log out of any linked services in your Parse server.
At any time, you can access the complete Android Project built with this tutorial at our Github repositories
Complete the previous guides so you can have a better understanding of the Parse User class.
Goal
To build a User LogIn and LogOut feature using Parse for a React Native App.
1 - Installing dependencies
At some point, every application in React Native will need screen navigation. You will now learn how to install and configure the most used library in React Native for this, react-navigation.
Go to your project root directory and install the following dependencies:
cd yourApp
yarn add @react-navigation/native react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
If you are developing for iOS, you need to install the pods to complete your app auto-linking:
cd ios
npx pod-install
Note: Linking is automatic for React native 0.60+ to all platforms, so if you are still using an older version of RN, take a look at React Native docs here.
In your app entry file (App.tsx or App.js), add this import line at the very top of the file. Now you need to move your components inside the react-navigation container, which will encapsulate your app inside a NavigationContainer:
App.tsx/App.js
1import"react-native-gesture-handler";2// Your other imports go here3import{ NavigationContainer }from"@react-navigation/native";45constApp=()=>{6return<NavigationContainer>{/* Your app code */}</NavigationContainer>;7}89exportdefault App;
The core navigation library has different additional navigation modules like a stack, tabs, drawer, others. Stack navigator is the most straightforward one and the one that you will use in this guide. Proceed with the installation:
# This is the navigator that you will use
yarn add @react-navigation/stack
2 - Creating a StackNavigator
Let’s now create and set up a StackNavigator. This module will manage and handle screen navigation on your app. Since it’s not a goal here to give you a react-navigation deep understanding, please go to the official docs to know more.
In your App.js (App.tsx if you are using TypeScript) file, import and create a StackNavigator, create a function containing your user registration screen and insert the navigator inside your app NavigationContainer. Your main file should look like this:
App.tsx/App.js
1import'react-native-gesture-handler';2import React from'react';3import{Image, SafeAreaView, StatusBar, Text, View}from'react-native';45import AsyncStorage from'@react-native-async-storage/async-storage';6import Parse from'parse/react-native';7import{NavigationContainer}from'@react-navigation/native';8import{createStackNavigator}from'@react-navigation/stack';9import{UserRegistration}from'./UserRegistration';10import Styles from'./Styles';1112// Your Parse initialization configuration goes here13 Parse.setAsyncStorage(AsyncStorage);14constPARSE_APPLICATION_ID:string='APPLICATION_ID';15constPARSE_HOST_URL:string='HOST_URL';16constPARSE_JAVASCRIPT_ID:string='JAVASCRIPT_ID';17 Parse.initialize(PARSE_APPLICATION_ID,PARSE_JAVASCRIPT_ID);18 Parse.serverURL =PARSE_HOST_URL;1920// Wrap your old app screen in a separate function, so you can create a screen21// inside the navigator; you can also declare your screens in a separate file, 22// export and import here to reduce some clutter23functionUserRegistrationScreen(){24return(25<>26<StatusBar />27<SafeAreaView style={Styles.login_container}>28<View style={Styles.login_header}>29<Image
30 style={Styles.login_header_logo}31 source={require('./assets/logo-back4app.png')}32/>33<Text style={Styles.login_header_text}>34<Text style={Styles.login_header_text_bold}>35{'React Native on Back4App - '}36</Text>37{' User registration'}38</Text>39</View>40<UserRegistration />41</SafeAreaView>42</>43);44}4546// Create your main navigator here47const Stack =createStackNavigator();4849// Add the stack navigator to your NavigationContainer50// and in it you can add all your app screens in the order you need51// them on your stack52constApp=()=>{53return(54<NavigationContainer>55<Stack.Navigator>56<Stack.Screen name="Sign Up" component={UserRegistrationScreen}/>57</Stack.Navigator>58</NavigationContainer>59);60};6162exportdefault App;
If you run your app now, you will notice the inclusion of a header at the top of the screen containing your screen name:
3 - Creating a login component
Let’s now build the UserLogIn functional component in your App. Create a new file in your root directory called UserLogIn.js (UserLogIn.tsx if you are using TypeScript) and add the input elements using state hooks to manage their data:
You can now implement the function that will call theParse.User.logInmethod, using state variables:
JavaScript
TypeScript
1constdoUserLogIn=asyncfunction(){2// Note that these values come from state variables that we've declared before3const usernameValue = username;4const passwordValue = password;5returnawait Parse.User.logIn(usernameValue, passwordValue)6.then(async(loggedInUser)=>{7// logIn returns the corresponding ParseUser object8 Alert.alert(9'Success!',10`User ${loggedInUser.get('username')} has successfully signed in!`,11);12// To verify that this is in fact the current user, currentAsync can be used13const currentUser =await Parse.User.currentAsync();14 console.log(loggedInUser === currentUser);15returntrue;16})17.catch((error)=>{18// Error can be caused by wrong parameters or lack of Internet connection19 Alert.alert('Error!', error.message);20returnfalse;21});22};
Insert this function inside the UserLogIn component, just before the return call, to be called and tested. Remember to update the form’s login button onPress action to () => doUserLogIn() and to import Alert from react-native. Your component should now look like this:
UserLogIn.js
UserLogIn.tsx
1import React,{FC, ReactElement, useState}from'react';2import{3 Alert,4 Image,5 Text,6 TextInput,7 TouchableOpacity,8 View,9}from'react-native';10import Parse from'parse/react-native';11import Styles from'./Styles';1213exportconst UserLogIn:FC<{}>=({}): ReactElement =>{14const[username, setUsername]=useState('');15const[password, setPassword]=useState('');1617constdoUserLogIn=asyncfunction():Promise<boolean>{18// Note that these values come from state variables that we've declared before19const usernameValue:string= username;20const passwordValue:string= password;21returnawait Parse.User.logIn(usernameValue, passwordValue)22.then(async(loggedInUser: Parse.User)=>{23// logIn returns the corresponding ParseUser object24 Alert.alert(25'Success!',26`User ${loggedInUser.get('username')} has successfully signed in!`,27);28// To verify that this is in fact the current user, currentAsync can be used29const currentUser: Parse.User =await Parse.User.currentAsync();30console.log(loggedInUser === currentUser);31returntrue;32})33.catch((error: object)=>{34// Error can be caused by wrong parameters or lack of Internet connection35 Alert.alert('Error!', error.message);36returnfalse;37});38};3940return(41<View style={Styles.login_wrapper}>42<View style={Styles.form}>43<TextInput
44 style={Styles.form_input}45 value={username}46 placeholder={'Username'}47 onChangeText={(text)=>setUsername(text)}48 autoCapitalize={'none'}49 keyboardType={'email-address'}50/>51<TextInput
52 style={Styles.form_input}53 value={password}54 placeholder={'Password'}55 secureTextEntry
56 onChangeText={(text)=>setPassword(text)}57/>58<TouchableOpacity onPress={()=>doUserLogIn()}>59<View style={Styles.button}>60<Text style={Styles.button_label}>{'Sign in'}</Text>61</View>62</TouchableOpacity>63</View>64<View style={Styles.login_social}>65<View style={Styles.login_social_separator}>66<View style={Styles.login_social_separator_line}/>67<Text style={Styles.login_social_separator_text}>{'or'}</Text>68<View style={Styles.login_social_separator_line}/>69</View>70<View style={Styles.login_social_buttons}>71<TouchableOpacity>72<View
73 style={[74 Styles.login_social_button,75 Styles.login_social_facebook,76]}>77<Image
78 style={Styles.login_social_icon}79 source={require('./assets/icon-facebook.png')}80/>81</View>82</TouchableOpacity>83<TouchableOpacity>84<View style={Styles.login_social_button}>85<Image
86 style={Styles.login_social_icon}87 source={require('./assets/icon-google.png')}88/>89</View>90</TouchableOpacity>91<TouchableOpacity>92<View style={Styles.login_social_button}>93<Image
94 style={Styles.login_social_icon}95 source={require('./assets/icon-apple.png')}96/>97</View>98</TouchableOpacity>99</View>100</View>101</View>102);103};
4 - Creating a login screen
Let’s now create a new screen for your app that will use your UserLogIn component. Add the new screen as the first (or top) screen of your StackNavigator as well:
App.tsx/App.js
1// ...23// Add this new screen function below the UserRegistrationScreen4functionUserLogInScreen(){5return(6<>7<StatusBar />8<SafeAreaView style={Styles.login_container}>9<View style={Styles.login_header}>10<Image
11 style={Styles.login_header_logo}12 source={require('./assets/logo-back4app.png')}13/>14<Text style={Styles.login_header_text}>15<Text style={Styles.login_header_text_bold}>16{'React Native on Back4App - '}17</Text>18{' User login'}19</Text>20</View>21<UserLogIn />22</SafeAreaView>23</>24);25}2627// ...2829// Add the screen as the top one at your StackNavigator30constApp=()=>{31return(32<NavigationContainer>33<Stack.Navigator>34<Stack.Screen name="Login" component={UserLogInScreen}/>35<Stack.Screen name="Sign Up" component={UserRegistrationScreen}/>36</Stack.Navigator>37</NavigationContainer>38);39};4041// ...
Go ahead and test your screen and component. Notice that your app will now show the user login screen instead of the user registration one, due to their placement on the StackNavigator screen list. You will see a message like this after signing in:
5 - Creating a Home Screen and handling navigation
After logging in, you will generally want to take the user to your app home screen. Create this screen in your app’s main file:
App.tsx/App.js
1// ...23// Add this new screen function below the UserRegistrationScreen4functionUserLogInScreen(){5return(6<>7<StatusBar />8<SafeAreaView style={Styles.login_container}>9<View style={Styles.login_header}>10<Image
11 style={Styles.login_header_logo}12 source={require('./assets/logo-back4app.png')}13/>14<Text style={Styles.login_header_text}>15<Text style={Styles.login_header_text_bold}>16{'React Native on Back4App - '}17</Text>18{' User login'}19</Text>20</View>21<UserLogIn />22</SafeAreaView>23</>24);25}2627// ...2829// Add the screen as the top one at your StackNavigator30constApp=()=>{31return(32<NavigationContainer>33<Stack.Navigator>34<Stack.Screen name="Login" component={UserLogInScreen}/>35<Stack.Screen name="Sign Up" component={UserRegistrationScreen}/>36</Stack.Navigator>37</NavigationContainer>38);39};4041// ...
Now you need to use ‘react-navigation’ to navigate the user after he logs in, adding this new code inside theUserLogIncomponent:
UserLogIn.js
UserLogIn.tsx
1// ...2// Add this import3import{useNavigation}from'@react-navigation/native';45exportconst UserLogIn:FC<{}>=({}): ReactElement =>{6// Add this to use useNavigation hook7const navigation =useNavigation();89// ...1011constdoUserLogIn=asyncfunction():Promise<boolean>{12const usernameValue:string= username;13const passwordValue:string= password;14returnawait Parse.User.logIn(usernameValue, passwordValue)15.then(async(loggedInUser: Parse.User)=>{16 Alert.alert(17'Success!',18`User ${loggedInUser.get('username')} has successfully signed in!`,19);20const currentUser: Parse.User =await Parse.User.currentAsync();21console.log(loggedInUser === currentUser);22// Add this to navigate your home screen; Navigation.navigate takes23// the user to the screen named after the one passed as parameter24 navigation.navigate('Home');25returntrue;26})27.catch((error: object)=>{28 Alert.alert('Error!', error.message);29returnfalse;30});31};3233// ...
You will be redirected to your new HomeScreen after logging in. You can upgrade this screen by adding this HelloUser component that shows the current user username:
HelloUser.js
HelloUser.tsx
1import React,{FC, ReactElement, useEffect, useState}from'react';2import{Text}from'react-native';3import Parse from'parse/react-native';4import Styles from'./Styles';56exportconst HelloUser:FC<{}>=({}): ReactElement =>{7// State variable that will hold username value8const[username, setUsername]=useState('');910// useEffect is called after the component is initially rendered and11// after every other render12useEffect(()=>{13// Since the async method Parse.User.currentAsync is needed to14// retrieve the current user data, you need to declare an async15// function here and call it afterwards16asyncfunctiongetCurrentUser(){17// This condition ensures that username is updated only if needed18if(username ===''){19const currentUser =await Parse.User.currentAsync();20if(currentUser !==null){21setUsername(currentUser.getUsername());22}23}24}25getCurrentUser();26},[username]);2728// Note the condition operator here, so the "Hello" text is only29// rendered if there is an username value30return(31<View style={Styles.login_wrapper}>32<View style={Styles.form}>33{username !==''&&<Text>{`Hello ${username}!`}</Text>}34</View>35</View>36);37};
Note: You can take a better look at React’s useEffect hooks here.
After calling this component inside your HomeScreen, your app should look like this:
6 - Creating a logout component
The UserLogOut component is simpler than the login since the Parse.User.logOut method takes no arguments and clears the currentUser data stored locally automatically. Create this component in your app root directory:
UserLogOut.js
UserLogOut.tsx
1import React,{FC, ReactElement}from'react';2import{Alert, Text, TouchableOpacity, View}from'react-native';3import Parse from'parse/react-native';4import{useNavigation}from'@react-navigation/native';5import{StackActions}from'@react-navigation/native';6import Styles from'./Styles';78exportconst UserLogOut:FC<{}>=({}): ReactElement =>{9const navigation =useNavigation();1011constdoUserLogOut=asyncfunction():Promise<boolean>{12returnawait Parse.User.logOut()13.then(async()=>{14// To verify that current user is now empty, currentAsync can be used15const currentUser: Parse.User =await Parse.User.currentAsync();16if(currentUser ===null){17 Alert.alert('Success!','No user is logged in anymore!');18}19// Navigation dispatch calls a navigation action, and popToTop will take20// the user back to the very first screen of the stack21 navigation.dispatch(StackActions.popToTop());22returntrue;23})24.catch((error: object)=>{25 Alert.alert('Error!', error.message);26returnfalse;27});28};2930return(31<View style={Styles.login_wrapper}>32<View style={Styles.form}>33<TouchableOpacity onPress={()=>doUserLogOut()}>34<View style={Styles.button}>35<Text style={Styles.button_label}>{'Logout'}</Text>36</View>37</TouchableOpacity>38</View>39</View>40);41};
Append this new component to HomeScreen so you can test it after signing in. Your app home screen will look like this now:
If you perform a successful logout, you will see a message like this while being redirected to the UserLogIn screen, which is the first one in the navigation stack:
Connect your UserRegistration to a registration button inside the UserLogIn screen and repeat the same redirection pattern to your app HomeScreen. Remember to read through react-navigation’s docs to discover several customization options and control every aspect of your app navigation.
UserLogIn.js
UserLogIn.tsx
1// ...23exportconst UserLogIn:FC<{}>=({}): ReactElement =>{4const navigation =useNavigation();56const[username, setUsername]=useState('');7const[password, setPassword]=useState('');89constdoUserLogIn=asyncfunction():Promise<boolean>{10// Note that these values come from state variables that we've declared before11const usernameValue:string= username;12const passwordValue:string= password;13returnawait Parse.User.logIn(usernameValue, passwordValue)14.then(async(loggedInUser: Parse.User)=>{15// logIn returns the corresponding ParseUser object16 Alert.alert(17'Success!',18`User ${loggedInUser.get('username')} has successfully signed in!`,19);20// To verify that this is in fact the current user, currentAsync can be used21const currentUser: Parse.User =await Parse.User.currentAsync();22console.log(loggedInUser === currentUser);23// Navigation.navigate takes the user to the screen named after the one24// passed as parameter25 navigation.navigate('Home');26returntrue;27})28.catch((error: object)=>{29// Error can be caused by wrong parameters or lack of Internet connection30 Alert.alert('Error!', error.message);31returnfalse;32});33};3435return(36<View style={Styles.login_wrapper}>37<View style={Styles.form}>38<TextInput
39 style={Styles.form_input}40 value={username}41 placeholder={'Username'}42 onChangeText={(text)=>setUsername(text)}43 autoCapitalize={'none'}44 keyboardType={'email-address'}45/>46<TextInput
47 style={Styles.form_input}48 value={password}49 placeholder={'Password'}50 secureTextEntry
51 onChangeText={(text)=>setPassword(text)}52/>53<TouchableOpacity onPress={()=>doUserLogIn()}>54<View style={Styles.button}>55<Text style={Styles.button_label}>{'Sign in'}</Text>56</View>57</TouchableOpacity>58</View>59<View style={Styles.login_social}>60<View style={Styles.login_social_separator}>61<View style={Styles.login_social_separator_line}/>62<Text style={Styles.login_social_separator_text}>{'or'}</Text>63<View style={Styles.login_social_separator_line}/>64</View>65<View style={Styles.login_social_buttons}>66<TouchableOpacity>67<View
68 style={[69 Styles.login_social_button,70 Styles.login_social_facebook,71]}>72<Image
73 style={Styles.login_social_icon}74 source={require('./assets/icon-facebook.png')}75/>76</View>77</TouchableOpacity>78<TouchableOpacity>79<View style={Styles.login_social_button}>80<Image
81 style={Styles.login_social_icon}82 source={require('./assets/icon-google.png')}83/>84</View>85</TouchableOpacity>86<TouchableOpacity>87<View style={Styles.login_social_button}>88<Image
89 style={Styles.login_social_icon}90 source={require('./assets/icon-apple.png')}91/>92</View>93</TouchableOpacity>94</View>95</View>96<>97<TouchableOpacity onPress={()=> navigation.navigate('Sign Up')}>98<Text style={Styles.login_footer_text}>99{"Don't have an account? "}100<Text style={Styles.login_footer_link}>{'Sign up'}</Text>101</Text>102</TouchableOpacity>103</>104</View>105);106};107108// ...
UserRegistration.js
UserRegistration.tsx
1// ...23exportconst UserRegistration:FC<{}>=({}): ReactElement =>{4const navigation =useNavigation();56const[username, setUsername]=useState('');7const[password, setPassword]=useState('');89constdoUserSignUp=asyncfunction():Promise<boolean>{10// Note that these values come from state variables that we've declared before11const usernameValue:string= username;12const passwordValue:string= password;13// Since the signUp method returns a Promise, we need to call it using await14returnawait Parse.User.signUp(usernameValue, passwordValue)15.then((createdUser: Parse.User)=>{16// Parse.User.signUp returns the already created ParseUser object if successful17 Alert.alert(18'Success!',19`User ${createdUser.get('username')} was successfully created!`,20);21// Navigation.navigate takes the user to the screen named after the one22// passed as parameter23 navigation.navigate('Home');24returntrue;25})26.catch((error: object)=>{27// signUp can fail if any parameter is blank or failed an uniqueness check on the server28 Alert.alert('Error!', error.message);29returnfalse;30});31};3233return(34<View style={Styles.login_wrapper}>35<View style={Styles.form}>36<TextInput
37 style={Styles.form_input}38 value={username}39 placeholder={'Username'}40 onChangeText={(text)=>setUsername(text)}41 autoCapitalize={'none'}42 keyboardType={'email-address'}43/>44<TextInput
45 style={Styles.form_input}46 value={password}47 placeholder={'Password'}48 secureTextEntry
49 onChangeText={(text)=>setPassword(text)}50/>51<TouchableOpacity onPress={()=>doUserSignUp()}>52<View style={Styles.button}>53<Text style={Styles.button_label}>{'Sign Up'}</Text>54</View>55</TouchableOpacity>56</View>57<View style={Styles.login_social}>58<View style={Styles.login_social_separator}>59<View style={Styles.login_social_separator_line}/>60<Text style={Styles.login_social_separator_text}>{'or'}</Text>61<View style={Styles.login_social_separator_line}/>62</View>63<View style={Styles.login_social_buttons}>64<TouchableOpacity>65<View
66 style={[67 Styles.login_social_button,68 Styles.login_social_facebook,69]}>70<Image
71 style={Styles.login_social_icon}72 source={require('./assets/icon-facebook.png')}73/>74</View>75</TouchableOpacity>76<TouchableOpacity>77<View style={Styles.login_social_button}>78<Image
79 style={Styles.login_social_icon}80 source={require('./assets/icon-google.png')}81/>82</View>83</TouchableOpacity>84<TouchableOpacity>85<View style={Styles.login_social_button}>86<Image
87 style={Styles.login_social_icon}88 source={require('./assets/icon-apple.png')}89/>90</View>91</TouchableOpacity>92</View>93</View>94<>95<TouchableOpacity onPress={()=> navigation.navigate('Login')}>96<Text style={Styles.login_footer_text}>97{'Already have an account? '}98<Text style={Styles.login_footer_link}>{'Log In'}</Text>99</Text>100</TouchableOpacity>101</>102</View>103);104};105106// ...
Your login and registration screens now should look like these:
Conclusion
At the end of this guide, you learned how to log in and log out Parse users on React Native and to navigate users through your application using react-navigation. In the next guide, we will show you how to perform useful user queries.