September 18, 2020

Build a Fully Featured React Chat App

Umar Elbelel

Introduction

Building a fully-featured chat app will technically require a lot of infrastructures such as a backend logic, a web socket, and more, fortunately, we have the CometChat infrastructures that covers everything we need to get started with our chat application to leverage on.

This tutorial would take you through the steps required in building a fully-featured group chat application with React. To instantiate this chat app, we will be using the CometChat custom UI KIT which will help us handle the logic at the frontend and also provide us with an appealing user interface for the chat application.

when completed we should have a fully featured chat app similar to the one below.


Setting Up a CometChat Account and Creating App

To create a CometChat API you have to first create an account with CometChat; after that follow the steps below to get your API key


  • Add a new app


Fill out the input fields with your desired details of the region, app name, technology, and use case.

Click on ADD APP to complete the process:



This will automatically setup your CometChat app with everything required for your integration.


Take note of your  APP ID and REGION, and AUTH KEY we will be using them later in our tutorial.


Initializing Project

Run the below command to create a new react project:

{% c-line %}npx create-react-app cometchat{% c-line-end %}

The preceding command will automatically create a new folder named CometChat and set up the necessary boilerplate for us to get started with our projects.

Installing CometChat SDK

Before we start implementing the appropriate required logics to make our chat application functional, we need to install CometChat Pro SDK. This is required for our app to properly interact with CometChat. For that purpose, move into the newly created project folder and install the SDK via NPM.

Run the below command to install

{% c-line %}npm install @cometchat-pro/chat@2.1.2 --save{% c-line-end %}

After installing our dependency we need to initialize it and to do that we have to include it at the starting point of our application. Open the "index.js"  file which is the starting point of our application and add the following content to it.


{% c-block language="javascript" %}
var appID = "APP_ID";
var region = "REGION";
var appSetting = new CometChat.AppSettingsBuilder().subscribePresenceForAllUsers().setRegion(region).build();
CometChat.init(appID, appSetting).then(
 () => {
   console.log("Initialization completed successfully");
 },
 error => {
   console.log("Initialization failed with error:", error);
 }
);
{% c-block-end %}


Don’t forget to replace the APP_ID and REGION placeholders with your credentials


Run the application and view your default homepage  on http://localhost:3000


Creating Components

Here we will start by creating our required components. First, a user will have to be authenticated before accessing the chat components. As mentioned earlier we will be leveraging on the CometChat UI KIT which provides us with robust chat components.


Cloning CometChat UI KIT

For us to utilize the features of COMETCHAT UI KIT, we first need to clone it to our application using the following commands

{% c-line %}git clone https://github.com/cometchat-pro/javascript-react-chat-ui-kit.git{% c-line-end %}


Now open the CometChat UI KIT folder and copy the CometChat folder. Navigate to your source folder and paste it there.

Next is for us to install all the needed dependency for the CometChat UI KIT, to do that open the “package.json” file in the CometChat UI KIT project we cloned with your text editor, Copy all contents from package.json in CometChat UI KIT to your package.json.

To install these packages run the following command

{% c-line %}npm install{% c-line-end %}


Now that we have setup our CometChat UI KIT we can easily reference and make use of the custom components to easily setup our interface for the application


Creating Login Component

Before we can access our message chat component, we need to be authenticated. To do that navigate to your source folder and create a folder called components (this is where all our components will be).

Once you have done that, the next is to create a login component “login.js”; and paste the code below,


{% c-block language="javascript" %}
import React  from 'react';
import { AuthContext } from '../context/authcontext';
export const Login = () => {
   const {login} = React.useContext(AuthContext)
   const [username, setUsername] = React.useState('')
   const [isSubmitting, setIsSubmitting] = React.useState(false)
   const formsubmit = async (e) =>{
       e.preventDefault()
       setIsSubmitting(true)
       const data = await login(username)
       if(data){
       setIsSubmitting(false)
       setUsername('')
       }
   }
   return(
       <div className="authContainer">
           <div className='container'>
           <div className='row'>
               <div className='col-md-4'></div>
               <div className='col-md-4'>
                   <div className="formContainer-1">
                       <h3 className="mb-5">Welcome to CometChatApp</h3>
                       <div className='row'>
                           <div className='ml-5' onClick={()=>{login('superhero1')}}>
                       <img src='https://data-us.cometchat.io/assets/images/avatars/ironman.png' height='50px' width='50px' alt='superher1'/>
                           <p>superhero1</p>
                           </div>
                           <div className='ml-5' onClick={()=>{login('superhero2')}}>
                       <img src='https://data-us.cometchat.io/assets/images/avatars/captainamerica.png' height='50px' width='50px' alt='superher2'/>
                           <p>superhero2</p>
                           </div>
                           <div className='ml-5' onClick={()=>{login('superhero3')}}>
                       <img src='https://data-us.cometchat.io/assets/images/avatars/spiderman.png' height='50px' width='50px' alt='superher3' />
                           <p>superhero3</p>
                           </div>
                    </div>
                    <br></br>
                       <form onSubmit={formsubmit}>
                           <div className='form-group'>
                               <input className='form-control' value={username} type="text" placeholder="Username"  onChange={(e)=> setUsername(e.target.value)}/>
                           </div>
                           {/* <div className='form-group'> */}
                               <div className="mt-5">
                                   <button type='submit' className='button' variant="secondary btn-action" size="lg" disabled={isSubmitting}>
                                       LOGIN {isSubmitting ? (<i className="fa fa-spinner fa-spin"></i>) : null}
                                   </button>
                               </div>
                           {/* </div> */}
                       </form>
                   </div>
               </div>
           </div>
           <div className='col-md-4'></div>
           </div>
       </div>
)
   }
{% c-block-end %}


The return method in the above code snippet displays an input field that accepts our username or UID, we have also provided you with default users (superhero1,superhero2,superhero3) for easy authentication. Next is we set the condition for our button upon submission.


On submission or onclick  of any of the default users, we trigger the login() which we set in our authcontext to handle our authentication.


Creating AuthContext Component

To complete our authentication we will have to first set up our authcontext component. This component handles our application states along with our login and logout logics.

To create this component, navigate to your src/context folder, and create a file called “authcontext.js” and paste the code below.

Don’t forget to replace the  AUTH_KEY  placeholder with your app’s Auth key.


{% c-block language="javascript" %}
import React from 'react'
import { useHistory } from 'react-router'
import  {CometChat} from '@cometchat-pro/chat'
import {AUTH_KEY} from '../constant/constant'
const defaultState = {
   user: null,
   IsLoggedIn:false,
   login: async (username) => {},
   logout: () => {},
 }
export const AuthContext = React.createContext(defaultState)
export const AuthConsumer = AuthContext.Consumer
export const AuthProvider= ({ children }) => {
 const history = useHistory()
 const [user, setUser] = React.useState(null)
 const [IsLoggedIn, setLoggedIn] = React.useState()
 React.useEffect(()=>{
   const refresh = async ()=> {
   const user = await CometChat.getLoggedinUser()
   if(user){
   setUser(user)
   setLoggedIn(true)
 }
 }
 refresh()
 },[])
 const login = async (username) => {
         const UID = username
     if(username){
       CometChat.createUser(user, AUTH_KEY).then(
         user => {
             console.log("user created", user);
             CometChat.login(UID,AUTH_KEY).then(
                 data => {
                   console.log(data)
                     setUser(data)
                     setLoggedIn(true)
                     history.push('/message')                  },
                 error => {
                   console.log("Login failed with exception:", { error });    
                 }
               );
         },error => {
             CometChat.login(UID,AUTH_KEY).then(
                 data => {
                   setUser(data)
                   setLoggedIn(true)
                   history.push('/message')
                 },
                 error => {
                   console.log("Login failed with exception:", { error });    
                 }
               );
         }
     )
     }else{
       history.push('/message')
     }        
 }
 const logout = async () => {
   CometChat.logout().then(user=>{
       setUser(null)
       setLoggedIn(false)
       history.push('/')
   });  
 }
 return (
   <AuthContext.Provider
     value={{ user,login, logout,IsLoggedIn}}
   >
     {children}
   </AuthContext.Provider>
 )
}
{% c-block-end %}


The login() handles our request, starting by validating if a user exists before authenticating the user using the CometChat.login() and also set IsloggedIn status to true, otherwise it creates the user using the CometChat.createUser() .Once the user is authenticated, you will be redirected to the chat component we will create in our next section.


Another method is the logout() with calls the cometchat.logout()  to logout a user.

For our styling, we use the bootstrap CDN included in our “index.html” file


Creating Chat Component

Begin by navigating to our src/components and create our “message.js” file; open the file and paste the code below


{% c-block language="javascript" %}
import React from 'react'
import {CometChatGroupListScreen } from "../CometChat";
import { AuthContext } from '../context/authcontext'
export const  Message = () => {
 const {logout} = React.useContext(AuthContext)
   return(
     <div>
         <button onClick={logout}>logout</button>
           <CometChatGroupListScreen/>
     </div>
   )
}
{% c-block-end %}

First we import the cometchatGrouplistScreen component from the CometChat SDK we cloned earlier.

This component will list all group and also handle all the logic of sending and receiving messages from group members.


Updating Our “app.js” File

Open your app.js file and paste the following code


{% c-block language="javascript" %}
import React from 'react';
import './App.scss';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { Message } from './components/Message';
import { Login } from './components/login';
import {ProtectedRoute} from './constant/ProtectedRoute'
import { AuthProvider } from './context/authcontext';
function App() {
 return (
   <BrowserRouter>
     <AuthProvider>
      <Switch>
       <Route path='/' exact component={Login}/>
       <ProtectedRoute path='/message' isPrivate component={Message}/>
     </Switch>
     </AuthProvider>
   </BrowserRouter>
 );
}
export default App;
{% c-block-end %}


Testing Our Application

In order to test our application, restart the application by pressing CTRL + C. Then run the following command to start it up:


{% c-line %}npm run start{% c-line-end %}


Navigate to your browser and open http://localhost:3000 to access the application


Conclusion

Leveraging on the robust and easy to use CometChat Custom UI KIT , we were able to build a fully featured react chat app without much predicament. The Custom UI KIT has provided us with most of our logic and basic chat interface, it also comes with more features (image upload, call, etc) when trying to extend your chat app.


Hope you found this tutorial helpful. Don’t forget to check the official documentation of CometChat to explore further and add more features. The complete source code to this tutorial is available on GitHub.