Today, you’ll implement Firebase Authentication in your chat app, enabling users to log in with their email and password. Authentication will allow personalized messaging and enhance the chat experience.
What You Will Do Today:
- Enable email/password authentication in Firebase.
- Create a login screen for users.
- Add user registration functionality.
- Redirect users to the chat screen upon successful login.
Step 1: Enable Email/Password Authentication in Firebase
- Open your Firebase Console.
- Go to Authentication > Sign-in method.
- Enable Email/Password authentication.
Step 2: Create the Login Screen
- Create a
LoginScreen.js
file in thescreens
folder.
// screens/LoginScreen.js
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, Alert } from 'react-native';
import auth from '@react-native-firebase/auth';
function LoginScreen({ navigation }) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async () => {
try {
await auth().signInWithEmailAndPassword(email, password);
navigation.replace('Chat');
} catch (error) {
Alert.alert('Login Error', error.message);
}
};
const handleRegister = async () => {
try {
await auth().createUserWithEmailAndPassword(email, password);
Alert.alert('Success', 'Account created! You can now log in.');
} catch (error) {
Alert.alert('Registration Error', error.message);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>Login</Text>
<TextInput
style={styles.input}
placeholder="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button title="Log In" onPress={handleLogin} />
<Button title="Register" onPress={handleRegister} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
},
input: {
width: '100%',
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 8,
padding: 10,
marginBottom: 10,
},
});
export default LoginScreen;
Step 3: Update Navigation for Authentication Flow
- Modify
App.js
to include the login screen and manage authentication state.
// App.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import auth from '@react-native-firebase/auth';
import LoginScreen from './screens/LoginScreen';
import ChatScreen from './screens/ChatScreen';
const Stack = createStackNavigator();
export default function App() {
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = auth().onAuthStateChanged((currentUser) => {
setUser(currentUser);
});
return unsubscribe; // Clean up listener on unmount
}, []);
return (
<NavigationContainer>
<Stack.Navigator>
{user ? (
<Stack.Screen name="Chat" component={ChatScreen} options={{ title: 'Chat' }} />
) : (
<Stack.Screen name="Login" component={LoginScreen} options={{ title: 'Login' }} />
)}
</Stack.Navigator>
</NavigationContainer>
);
}
- This code conditionally renders the ChatScreen or LoginScreen based on the user’s authentication state.
Step 4: Add Logout Functionality
- Update
ChatScreen.js
to include a logout button:
import React, { useState, useEffect } from 'react';
import { View, Button, FlatList, StyleSheet, Text } from 'react-native';
import auth from '@react-native-firebase/auth';
import firestore from '@react-native-firebase/firestore';
function ChatScreen() {
const [messages, setMessages] = useState([]);
useEffect(() => {
const unsubscribe = firestore()
.collection('messages')
.orderBy('createdAt', 'desc')
.onSnapshot((querySnapshot) => {
const fetchedMessages = querySnapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setMessages(fetchedMessages);
});
return unsubscribe;
}, []);
const handleLogout = () => {
auth().signOut();
};
const renderMessage = ({ item }) => (
<View style={styles.messageContainer}>
<Text style={styles.messageUser}>{item.userName}</Text>
<Text style={styles.messageText}>{item.text}</Text>
<Text style={styles.messageTimestamp}>
{item.createdAt?.toDate().toLocaleTimeString()}
</Text>
</View>
);
return (
<View style={styles.container}>
<FlatList
data={messages}
renderItem={renderMessage}
keyExtractor={(item) => item.id}
inverted
/>
<Button title="Logout" onPress={handleLogout} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
messageContainer: {
marginVertical: 8,
padding: 10,
backgroundColor: '#e1ffc7',
borderRadius: 8,
alignSelf: 'flex-start',
},
messageUser: {
fontWeight: 'bold',
marginBottom: 4,
},
messageText: {
fontSize: 16,
},
messageTimestamp: {
fontSize: 12,
color: '#888',
marginTop: 4,
alignSelf: 'flex-end',
},
});
export default ChatScreen;
Step 5: Test Authentication Flow
- Run the app:
- For Android:
npx react-native run-android
- For iOS:
npx react-native run-ios
- For Android:
- Test user registration:
- Enter an email and password, then press Register.
- Check the Firebase Console under Authentication for the new user.
- Test login:
- Log in with the registered email and password.
- You should be redirected to the ChatScreen.
- Test logout:
- Press the Logout button.
- You should be redirected to the LoginScreen.
Summary
Today, you implemented user authentication using Firebase Authentication. Users can now register, log in, and log out securely. This enables personalized chat experiences and secure access to the app.
Tomorrow, you’ll focus on managing message data in Firestore for optimized querying and scalability.