Open In App

Chat Application using React Hooks and Firebase

Last Updated : 07 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In the era of technology messaging apps have become an aspect of our everyday routines enabling us to engage and interact with others promptly. For developers interested in crafting their messaging app leveraging React Hooks in conjunction, with Firebase presents a strategy, for constructing a dynamic, responsive, and expandable chat system. This piece will delve into the process of developing a messaging app using React Hooks and Firebase showcasing its features and advantages throughout.

Output Preview: Let us have a look at how the final output will look like.

LoggedIn

Chat Room In logged in State

Prerequisites:

Approach to Create Chat Application:

  • Authentication: Use Firebase Authentication for user sign-in and sign-out.
  • Navbar: Create a Navbar component to display the app title and sign-in/sign-out buttons based on user authentication status.
  • Chat Component: Implement a Chat component to display messages and allow users to send new messages using Firebase Firestore.
  • Message Component: Develop a Message component to display individual messages with sender information.
  • Styling: Apply styling to components for a visually appealing interface.
  • Testing and Deployment: Test thoroughly and deploy your app to a hosting platform like Firebase Hosting.
  • Message History: In the chat app past messages will be. Shown to users when they enter the chat room.
  • Users have the ability to exchange messages instantly through real time messaging facilitating communication.
  • Users can create an account. Access the chat app, by google sign in method for authentication.

Steps to Create Chat Application using React Hooks:

Step 1: Create a new project using below command

npx create-react-app chat-app

Step 2: While all the packages are installing lets create a project in Firebase.

  • Head over to the Firebase dashboard
  • Create a new project
  • Once your project is set up you will have to configure a Firestore database and activate authentication for your project.
  • Remember to save your Firebase setup information as it will be necessary on, in our React application.

Step 3: Install Required Dependencies Like Firebase & React Firebase Hooks using below command

npm install firebase react-firebase-hooks

Step 4: Install TailwindCSS

npm install -D tailwindcss
npx tailwindcss init

Step 5: Setup TailwindCSS Configuration By Adding Below Code to tailwind.config.js file in Content Section

"./src/**/*.{js,jsx,ts,tsx}"

Step 6: Import Below Code to index.css file

@tailwind base;
@tailwind components;
@tailwind utilities;

Folder Structure:

structure

Project structure

The updated dependencies in package.json file will look like:

"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"firebase": "^9.9.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-firebase-hooks": "^5.0.3",
"react-google-button": "^0.7.2",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}

Step 7:Connect Your Firebase Project With Your App:

Now that we’ve got our project ready lets go ahead and link it to our Firebase project. Make a file called firebase.js and insert the code below making sure to swap out the setup specifics with your own;

Javascript




// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
// TODO: Add SDKs for Firebase products that you want to use
import { getAuth } from "firebase/auth";
import { getFirestore } from 'firebase/firestore'
 
 
// Your web app's Firebase configuration
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
};
 
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app)
export const db = getFirestore(app)


Javascript




// App.js
import React from 'react';
import Navbar from './components/Navbar';
import Chat from './components/Chat';
 
import { auth } from './firebase';
import {
    useAuthState
} from 'react-firebase-hooks/auth';
 
const style = {
    appContainer: `max-w-[728px] mx-auto text-center`,
    sectionContainer: `flex flex-col h-[90vh]
         bg-gray-100 mt-10 shadow-xl border relative`,
};
 
function App() {
    const [user] = useAuthState(auth);
    //  console.log(user)
    return (
        <div className={style.appContainer}>
            <section className='{style.sectionContainer}'>
             
                <Navbar />
                {user ? <Chat /> : null}
            </section>
        </div>
    );
}
 
export default App;


Javascript




// Chat.jsx
import React, {
    useState,
    useEffect,
    useRef
} from 'react';
import Message from './Message';
import SendMessage from './SendMessage';
import { db } from '../firebase';
import {
    query,
    collection,
    orderBy,
    onSnapshot
} from 'firebase/firestore';
 
const style = {
    main: `flex flex-col p-[10px]`,
};
 
const Chat = () => {
    const [messages, setMessages] = useState([]);
    const scroll = useRef();
 
    useEffect(() => {
        const q = query(collection(db, 'messages'),
            orderBy('timestamp'));
        const unsubscribe = onSnapshot(q, (querySnapshot) => {
            let messages = [];
            querySnapshot.forEach((doc) => {
                messages.push({ ...doc.data(), id: doc.id });
            });
            setMessages(messages);
        });
        return () => unsubscribe();
    }, []);
 
    return (
        <>
            <main className={style.main}>
                {messages &&
                    messages.map((message) => (
                        <Message key={message.id}
                            message={message} />
                    ))}
            </main>
            {/* Send Message Compoenent */}
            <SendMessage scroll={scroll} />
            <span ref={scroll}></span>
        </>
    );
};
 
export default Chat;


Javascript




// Message.jsx
import React from 'react';
import { auth } from '../firebase'
 
const style = {
    message: `flex items-center shadow-xl m-4
       py-2 px-3 rounded-tl-full rounded-tr-full`,
    name: `absolute mt-[-4rem]
           text-gray-600 text-xs`,
    sent: `bg-[#395dff] text-white flex-row-reverse
           text-end float-right rounded-bl-full`,
    received: `bg-[#e5e5ea] text-black
               float-left rounded-br-full`,
};
 
const Message = ({ message }) => {
    const messageClass =
        message.uid === auth.currentUser.uid
            ? `${style.sent}`
            : `${style.received}`
 
    return (
        <div>
            <div className={`${style.message}
      ${messageClass}`}>
                <p className={style.name}>
                    {message.name}
                </p>
                <p>{message.text}</p>
            </div>
        </div>
    );
};
 
export default Message;


Javascript




// NavBar.jsx
import React from 'react';
import SignIn from './SignIn'
import LogOut from './LogOut'
import { auth } from '../firebase'
import {
    useAuthState
} from 'react-firebase-hooks/auth'
const style = {
    nav: `bg-green-600 h-20 flex justify-between
     items-center p-4`,
    heading: `text-white text-3xl
    flex justify-between items-center p-4`
}
 
const Navbar = () => {
    const [user] = useAuthState(auth)
    console.log(user)
    return (
        <div className={style.nav}>
            <h1 className={style.heading}>
                Geeks Chat App
            </h1>
            {user ? <LogOut /> : <SignIn />}
 
        </div>
    );
};
 
export default Navbar;


Javascript




// SendMessage.jsx
import React, { useState } from 'react';
import {
    auth,
    db
} from '../firebase'
import {
    addDoc,
    collection,
    serverTimestamp
} from 'firebase/firestore'
 
const style = {
    form: `h-14 w-full max-w-[728px] flex text-xl absolute bottom-0`,
    input: `w-full text-xl p-3 bg-white-900 text-black outline-none border-none`,
    button: `w-[20%] bg-green-500`,
};
 
const SendMessage = ({ scroll }) => {
    const [input, setInput] = useState('');
 
    const sendMessage = async (e) => {
        e.preventDefault()
        if (input === '') {
            alert('Please enter a valid message')
            return
        }
        const { uid, displayName } = auth.currentUser
        await addDoc(collection(db, 'messages'), {
            text: input,
            name: displayName,
            uid,
            timestamp: serverTimestamp()
        })
        setInput('')
        scroll.current.scrollIntoView({ behavior: 'smooth' })
    }
 
    return (
        <form onSubmit={sendMessage} className={style.form}>
            <input
                value={input}
                onChange={(e) => setInput(e.target.value)}
                className={style.input}
                type='text'
                placeholder='Message'
            />
            <button className={style.button} type='submit'>
                Send
            </button>
        </form>
    );
};
 
export default SendMessage;


Javascript




// Signin.jsx
import React from 'react'
import GoogleButton from 'react-google-button'
 
import { auth } from '../firebase'
import {
    GoogleAuthProvider,
    signInWithRedirect
} from 'firebase/auth'
 
const style = {
    wrapper: `flex justify-center`
}
 
const googleSignIn = () => {
    const provider = new GoogleAuthProvider()
    signInWithRedirect(auth, provider)
}
 
const SignIn = () => {
    return (
        <div className={style.wrapper}>
            <GoogleButton onClick={googleSignIn} />
        </div>
    )
}
 
export default SignIn


Javascript




// LogOut.jsx
import React from 'react'
import { auth } from '../firebase'
 
const style = {
    button: `bg-gray-200 px-4 py-2 hover:bg-gray-100`
}
 
 
const LogOut = () => {
    const signOut = () => {
        signOut(auth)
    }
 
    return (
        <button onClick={() => auth.signOut()}
            className={style.button}>
            Logout
        </button>
    )
}
 
export default LogOut


To start the app run the following command.

npm start

Output:

giphy

Output



Like Article
Suggest improvement
Share your thoughts in the comments