Building a Minimal Chat App with React Native and Expo Managed Workflow


Introduction
In this tutorial, we will build a minimal chat app using React Native and Expo managed workflow. We'll use Firebase Firestore as our backend to handle real-time data synchronization.
Step-by-Step Guide
1. Setting Up the Project
First, set up a new Expo project and install the necessary dependencies:
expo init ChatApp cd ChatApp expo install firebase expo install @react-native-async-storage/async-storage
2. Configuring Firebase
Create a Firebase project at Firebase Console. Add a new web app and get the Firebase configuration details.
Create a firebaseConfig.js
file to initialize Firebase:
// firebaseConfig.js import firebase from 'firebase/app'; import 'firebase/firestore'; const firebaseConfig = { apiKey: 'YOUR_API_KEY', authDomain: 'YOUR_AUTH_DOMAIN', projectId: 'YOUR_PROJECT_ID', storageBucket: 'YOUR_STORAGE_BUCKET', messagingSenderId: 'YOUR_MESSAGING_SENDER_ID', appId: 'YOUR_APP_ID', }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig); } const db = firebase.firestore(); export { db };
3. Creating the Chat Interface
Create a ChatScreen.js
component to display and send messages:
// ChatScreen.js import React, { useState, useEffect } from 'react'; import { View, Text, TextInput, Button, FlatList, StyleSheet } from 'react-native'; import { db } from './firebaseConfig'; import AsyncStorage from '@react-native-async-storage/async-storage'; const ChatScreen = () => { const [message, setMessage] = useState(''); const [messages, setMessages] = useState([]); const [username, setUsername] = useState(''); useEffect(() => { (async () => { const storedUsername = await AsyncStorage.getItem('username'); if (storedUsername) { setUsername(storedUsername); } else { const newUsername = `User${Math.floor(Math.random() * 1000)}`; await AsyncStorage.setItem('username', newUsername); setUsername(newUsername); } })(); const unsubscribe = db.collection('messages').orderBy('timestamp', 'desc').onSnapshot((snapshot) => { setMessages(snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }))); }); return () => unsubscribe(); }, []); const sendMessage = async () => { if (message.trim().length > 0) { await db.collection('messages').add({ text: message, username, timestamp: firebase.firestore.FieldValue.serverTimestamp(), }); setMessage(''); } }; return ( <View style={styles.container}> <FlatList data={messages} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <View style={styles.messageContainer}> <Text style={styles.username}>{item.username}:</Text> <Text style={styles.message}>{item.text}</Text> </View> )} inverted /> <View style={styles.inputContainer}> <TextInput style={styles.input} value={message} onChangeText={setMessage} placeholder="Type a message" /> <Button title="Send" onPress={sendMessage} /> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 10, backgroundColor: '#fff', }, messageContainer: { flexDirection: 'row', marginBottom: 10, }, username: { fontWeight: 'bold', marginRight: 5, }, message: { flexShrink: 1, }, inputContainer: { flexDirection: 'row', alignItems: 'center', borderTopWidth: 1, borderColor: '#ddd', paddingTop: 10, }, input: { flex: 1, borderWidth: 1, borderColor: '#ddd', borderRadius: 5, padding: 10, marginRight: 10, }, }); export default ChatScreen;
4. Integrating the ChatScreen in the App
Update App.js
to use the ChatScreen
component:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import ChatScreen from './ChatScreen'; const Stack = createStackNavigator(); export default function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Chat" component={ChatScreen} /> </Stack.Navigator> </NavigationContainer> ); }
Explanation
- Firebase Configuration: Set up Firebase and initialize Firestore.
- Chat Interface: The
ChatScreen
component handles displaying and sending messages. - Real-time Updates: Use Firestore's snapshot listener to get real-time updates.
- Unique Usernames: Generate and store unique usernames using AsyncStorage.
Conclusion
This tutorial shows you how to build a minimal chat app using React Native, Expo, and Firebase. This simple yet functional app can be a starting point for more advanced features like authentication, media messages, and more complex chat functionalities.