How to Add @Mentions to a React Chat App

Follow along with this step-by-step tutorial to add ‘@’ mentions in a React chat application.

Hiep Le • Oct 6, 2021

App and web development have come a long way over the last few years. We use a lot of chat applications every day, including Facebook Messenger, WhatsApp, Snapchat, and so on. One of the most widely used features is live chat. Whenever the @ symbol is typed in the message composer of a group, you can show a list of users in that group. On clicking of a particular user's name in that list, a text with the user's name and uid gets inserted in the composer. Using the CometChat communications SDK, CometChat React UI Kit, and Firebase backend services, you will learn how to add mentions to react chat app with minimal effort.

Follow along the steps to add mentions to React chat app that will provide:

  • A way for end-users to signup (email, password and user’s name are required).

  • A way for users to log in and have a short profile (Name, UID, Photo, About).

  • List of Users/Contacts is visible to all users with a search bar.

  • All users can send and receive text messages to individual users and groups.

  • Users can create/exit groups and add/remove other users.

  • Users can @ tag or mention other users in personal and group chat.

  • When a user types ‘@’ in the chatbox, a list of all users in the group must be displayed to select from.

  • Login the logged-in user to CometChat.

  • High Quality UI by using React UI Kit.

  • Add API call when a user registers so that the user is created in CometChat.

This tutorial will use React, Firebase, and CometChat to add mentions to React chat application.

Prerequisites

To follow this tutorial, you must have a degree of understanding of the general use of React.js. This will help you to improve your understanding of this tutorial.

Installing the App Dependencies

  • Step 1: you need to have Node.js installed on your machine

  • Step 2: create a new project with the name react-mention-chat-app by running the following statement.

    npx create-react-app react-mention-chat-app

  • Step 3: you need to install some dependencies such as CometChat Pro, Firebase, Validator, Uuid, Tribute.

    npm install @cometchat-pro/chat firebase uuid validator tributejs --save
    # or
    yarn add @cometchat-pro/chat firebase uuid validator tributejs

Configuring CometChat SDK

  1. Head to CometChat Pro and create an account.

  2. From the dashboard, add a new app called "react-mention-chat-app".

  3. Select this newly added app from the list.

  4. From the Quick Start copy the APP_ID, REGION, and AUTH_KEY, which will be used later.

  5. Navigate to the Users tab, and delete all the default users and groups leaving it clean (very important).

  6. Create a file called .env in the root folder of your project.

  7. Import and inject your secret keys in the .env file containing your CometChat and Firebase in this manner.

    REACT_APP_FIREBASE_API_KEY=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    REACT_APP_FIREBASE_AUTH_DOMAIN=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    REACT_APP_FIREBASE_DATABASE_URL=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    REACT_APP_FIREBASE_STORAGE_BUCKET=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    REACT_APP_FIREBASE_PROJECT_ID=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    
    REACT_APP_COMETCHAT_APP_ID=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    REACT_APP_COMETCHAT_REGION=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx
    REACT_APP_COMETCHAT_AUTH_KEY=xxx-xxx-xxx-xxx-xxx-xxx-xxx-xxx

  8. Make sure to include .env in your gitIgnore file from being exposed online.

Setting Up Firebase Project

Head to Firebase to create a new project and activate the email and password authentication service. This is how you do it:

To begin using Firebase, you’ll need a Gmail account. Head over to Firebase and create a new project.

Firebase

Firebase

Firebase provides support for authentication using different providers. For example, Social Auth, phone numbers, as well as the standard email and password method. Since we’ll be using the email and password authentication method in this tutorial, we need to enable this method for the project we created in Firebase, as it is by default disabled.

Under the authentication tab for your project, click the sign-in method and you should see a list of providers currently supported by Firebase.

s acfbfbbadcbcbbfbcadbcea image

Firebase Authentication

Next, click the edit icon on the email/password provider and enable it.

s acfbfbbadcbcbbfbcadbcea image

Enable Firebase Authentication with Email and Password

Now, you need to go and register your application under your Firebase project. On the project’s overview page, select the add app option and pick web as the platform.

s acfbfbbadcbcbbfbcadbcea image

Firebase Dashboard

Once you’re done registering the application, you’ll be presented with a screen containing your application credentials.

s cccfcdccfeadedceaaeaeeacb image

Firebase Credentials

Please update your created “config.js” file with the above corresponding information. If you do not see the information for the “databaseUrl” field in the config.js file. Please do not worry we will discuss it in the “Configuring the Firebase” section.

Congratulations, now that you're done with the installations, let's do some configurations.

Configuring Styling for the Application

Inside your project structure, open the index.css files and paste the codes here. index.css file will contain all CSS of the application.

Initializing CometChat for the Application

The below codes initialize CometChat in your app before it spins up. The App.js file uses your CometChat API Credentials. We will get CometChat API Credentials from the .env file. Please do not share your secret keys on GitHub.

Actually, App.js does not contain only the above code. It also contains other business logic of the application. The full source code of App.js file can be found here.

Configuring the Firebase File

You need to create a “firebase.js” file inside the “src” folder and you need to enable Firebase realtime database by following the below steps.

Realtime Database

Choose “Realtime Database” option

Create Database

Click on “Create Database"

Select location where you realtime database will be stored

Select location where you realtime database will be stored

Select “Start in test mode” for the learning purpose

Select “Start in test mode” for the learning purpose

Please follow the guidance from Firebase. After following all steps, you will see the database URL. If you just need to update the “databaseUrl” field in your “config.js” file with that value.

Database Url

Database Url

On the other hand, your Firebase real-time database will be expired in the future. To update the rules you just need to select the “Rules” tab and update the date/time in milliseconds as you can see in the image below.

Update Firebase Realtime Database Rules

Update Firebase Realtime Database Rules

While developing the application, you may see a warning message on the console.

To resolve the issue, you need to update the rules for your real-time database as follow:

Update database rules for better performance

Update database rules for better performance

For more information about the warning message and how to fix, you can refer to this link.

This file is responsible for interfacing with Firebase authentication and database services. Also, it makes ready our google authentication service provider enabling us to sign in with google. Secret keys will be stored in the .env file. As mentioned above, please do not share your secret keys on GitHub.

The below images demonstrate the data structure of the application. A user should have an avatar, an email, an id, a user’s name.

Data Structure - User

Data Structure - User.

Project Structure

The image below reveals the project structure. Make sure you see the folder arrangement before proceeding.

Now, let's make the rest of the project components as seen in the image above.

Project Structure

Project Structure

The App.js File

The App.js file is responsible for rendering different components by the given routes. For example, it will render the login page if the user has not logged in, yet or it renders the home page if the user has signed in to the system. On other hand, it will be used to initialize CometChat.

The full source code of the App.js file can be found here.

The Loading Component

The loading component will be shown when the system performs some side effects such as interacting with Firebase or calling CometChat APIs and so on. This component will be used to increase user experience. If we do not have this component, the end-users cannot know when the data is loaded successfully.

The full source code of the loading component can be found here.

The Login Component

This component is responsible for authenticating our users using the Firebase google authentication service. It accepts the user credentials and either signs him up or in, depending on if he is new to our application. See the code below and observe how our app interacts with Firebase and the CometChat SDK. The full source code can be found here.

The above code indicates that we are using withModal as a higher-order component. This higher-order component will be used to reuse the code of showing and hiding the custom modal. In this case, we want to show the sign-up modal to let end-users register new accounts. We will discuss the sign-up component in the following section.

The Sign Up Component

The sign-up component will help end-users to register new accounts. This component will do two things. The first thing is to register new accounts on Firebase by using the Firebase authentication service. Aside from that, it also registers new accounts on CometChat by using the CometChat SDK. The full source code can be found here.

Adding CometChat UI to our Application

Before adding @Mentions to our React chat app, we need to set up the chat feature first. Fortunately, CometChat team provides React UI Kit that contains full features for our chat application. Therefore, in this section, we are using React UI Kit v3.0. To do that, follow the next steps:

  • Step 1: Clone the CometChat Pro React UI Kit Repository like so:

    git clone https://github.com/cometchat-pro/cometchat-pro-react-ui-kit.git -b v3

  • Step 2: Copy the folder of the CometChat Pro React UI Kit you just cloned into the src folder of your project:

Copy the cloned folder in to the src folder

Copy the cloned folder in to the src folder

React UI Kit Dependencies

React UI Kit Dependencies

  • Step 3: Copy all the dependencies from the package.json file of the CometChat Pro React UI Kit folder and paste them in the dependencies section of the package.json file of your project.

  • Step 4: Save the file and install the dependencies like so: npm install

As soon as the installation is completed, you now have access to all the React UI Components. The React UI kit contains different chat UI components for different purposes as you can see in the documentation here. It includes:

1. CometChatUI

2. CometChatUserListWithMessages

3. CometChatGroupListWithMessages

4. CometChatConversationListWithMessages

5. CometChatMessages

6. CometChatUserList

7. CometChatGroupList

8. CometChatConversationList

The Home View

This is where all the magic happens. This component embodies other sub-components like the Header, Chat, etc.

As intuitive as they sound, the above sub-components can be best observed in the image below.

Header Component, Chat Component & Home Component

Header Component, Chat Component & Home Component

The Header Component

Header Component

Header Component

The header component will be used to demonstrate the header of the page. It contains the logo the greeting and the logout button. The full source code of the header component can be found here.

The Chat Component

Chat Component

Chat Component

This component will use CometChat React UI Kit. As mentioned above, CometChat React UI Kit provides many cool features that we need for our React chat application. The full source code can found from here.

Enabling the Mention Extension

According to the CometChat documentation, you need to follow the below steps to enable the mentions extension.

  • Step 1: Login to the CometChat dashboard.

  • Step 2: Select one of your apps. In this case, I will select “mention-chat-app”.

Select one of your apps

Select one of your apps

  • Step 3: Select “Extensions” to open the Extensions page.

Select “Extensions” to open the “Extensions” page

Select “Extensions” to open the “Extensions” page

  • Step 4: Enable “Mentions”.

Enable “Mentions”

Enable “Mentions”

Customize React UI Kit

It is time to add mentions to our React chat application. We need to achieve the below requirements.

  1. Users can @ tag or mention other users in personal and group chat.

  2. When a user types ‘@’ in the chatbox, a list of all users in the group must be displayed to select from.

To implement the above requirements, we need to follow the below steps:

  • Step 1: We are focusing when building chat feature. For example, we will turn off some features and focus on what we would like to build. In order to achieve that, you just need to update the “UIKitSettings.js” file. The full source code can be found here.

  • Step 2: As mentioned above, we need to create the “tribute.css” file inside the “CometChatMessageComposer” folder. Because we are using the tribute library to show list of users when typing “@” on the chat-box. The full source code of the “tribute.css” file can be found from here.

    .tribute-container {
      background: #fff;
      border-radius: 0.5rem;
      border: 1px solid #E5E7EB;
      max-height: 15rem;
      overflow: auto;
      padding: 0.75rem;
      top: 27.625rem !important;
      z-index: 10000;
    }
    
    .tribute-container ul { 
      list-style-type: none;
    }
    
    .tribute-container ul li { 
      padding: 0.25rem;
    }
    
    .tribute-container ul li:hover {
      cursor: pointer;
    }

  • Step 3: Import the tribute library and the “tribute.css” file in the index.js file which is inside the “CometChatMessageComposer” folder.

    ...
    import Tribute from "tributejs";
    import "./tribute.css";
    ...

  • Step 4: Inside that index.js file, we need to write the logic to attach the tribute to the chatbox.

    https://gist.github.com/swahaniroy/51fdc97516998cc12dbea902ec363730

We need to create the “groupListenerId” and then use it in the “onNewMemberJoined” function because we want to update the list of members for the tribute when the group’s members have been changed. For example, when a member has been clicked or a new member joins the group and so on.

On the other hand, we define the “tributeRef” to store the list of values for the tributes. It means that when the user is typing ‘@’, this list will be used to find the suggested members. Following that the “prevItemType” ref is defined to compare with the current type of the selected conversation. This part will be used in the “componentDidUpdate” method and will help us to re-initialize the list of values for the tribute when the user changes the conversation type such as changes between the private chat and the group chat.

When the user inputs the message composer. In the case, the user is mentioned someone. We need to convert the input text message into the fomat “@{username|uid}”. The formatted message will be used to call the API. The “transformTextMessage” and “processTransformMessageInput” help us to achieve that.

The “enableMentions” function needs to be called in the "componentDidMount” function and the “componentDidUpdate” function. We need to check whether the mentions extension was enabled, or not. If it was enabled, we will continue to set up the mentions feature. We will reuse the existing “getReceiverDetails” function to determine a current receiver is a group or a user. If the current receiver is a group, we will call the “initTributeForGroup” function and if the current receiver is a user, we will call the “initTributeforUser” function.

the “initTributeForGroup” function and the “initTributeForUser” have the same purpose. They are created to initialize the list of suggested users for the tribute when typing “@” on the chatbox. in the “initTributeForUser”, we will the CometChat service to get the user’s information and we get the information of users for the selected group in the “initTributeForUser” function. When fetching the list of users from the selected group, the CometChat API will return a response including much data inside it. However, to initialize the tribute, we just need the name of each user. For this reason, the “transformGroupMembers “ function is created to transform the response before setting the data for the tribute.

The full source code can be found here.

  • Step 5: To increase our user experience, we need to show a toast when an user was tagged by another user. We find the “setToastMessage” function in the “CometChatContext.js” file, if it is commented, we need to uncomment it.

    ...
    setToastMessage = (type, message) => {
      switch(type) {
    
          case "error":
              this.toastRef.setError(message);
          break;
          case "success":
              this.toastRef.setSuccess(message);
              break;
          case "info":
              this.toastRef.setInfo(message);
              break;
          case "warning":
              this.toastRef.setWarning(message);
              break;
          default:
          break;
      }
    
      return null;
    };
    ...

  • Step 6: Find the index.js inside the “CometChatMessageList” folder and update the “messageUpdated” function. The below code snippet determines that we will call the “showToastForMentionMessage” after receiving a text message. The “showToastForMentionMessage” takes responsibility for showing a toast so a user can know whenever he or she was mentioned by another user. For simplicity, the “showToastForMentionMessage” will show a toast whenever the text message contains “@username”. For example, if the text message contains “@David”, the user, whose user’s name is David, will see a toast. The full source code can be found here.

    ..
    showToastForMentionMessage = (message) => { 
      if (message.text.includes(`@${this.state.loggedInUser.name}`)) {
        const toastMessage = `You was tagged by ${message.sender.name}`;
        this.context.setToastMessage("success", toastMessage);
      }
    }
    
    //callback for listener functions
    messageUpdated = (key, message, group, options) => {
      ...
      case enums.TEXT_MESSAGE_RECEIVED:
      case enums.MEDIA_MESSAGE_RECEIVED:
        this.showToastForMentionMessage(message);
        this.onMessageReceived(message);
        break;
       ...
    };
    ...

  • Step 7: When fetching the messages from the server. Each message, which is from the server, will have “@{username|uid}” format. We cannot show that format on the UI, of course. To increase the UX, we need to transform the message to “@username” format. For this reason, we need to update the “CometChatMessages” and “CometChatMessageList” components.

    class CometChatMessages extends React.PureComponent {
      ...	
    	messageSent = messages => {
    		const message = messages[0];
    		const messageList = [...this.state.messageList];
    
    		let messageKey = messageList.findIndex(m => m._id === message._id);
    		if (messageKey > -1) {
    			const newMessageObj = { ...message };
    			const transformedMessage = this.messageListRef.transformSingleMessage(newMessageObj);
    
    			messageList.splice(messageKey, 1, transformedMessage);
    			messageList.sort((a, b) => a.id - b.id);
    			this.setState({ messageList: messageList, scrollToBottom: true });
    		}
    	};
    
    	//message is received or composed & sent
    	appendMessage = message => {
    		const cloneObject = {...message[0]};
    		const transformedMessage = this.messageListRef.transformSingleMessage(cloneObject);
    		let messages = [...this.state.messageList, transformedMessage];
    		this.setState({ messageList: messages, scrollToBottom: true });
    	};
      ...
    }

After the user has sent the input message. We need to convert it into the appropriate format before rendering it on the list. Therefore, we need to modify the two above functions - the “appendMessage” function and the “messageSent” function. Both of them will call transformSingleMessage function from the “CometChatMessageList” component by using the “messageListRef”. The full source code of the “CometChatMessages” component can be found here.

The above code snippet will help us to transform the list of messages when fetching from the server or the message that will be received while talking to other users. the “transformSingleMessage” helps us to achieve that. The full source code of the “CometChatMessageList” component can be found here.

Conclusion

In conclusion, we have done an amazing job in adding mentions for a React chat app by leveraging React.js, Firebase, CometChat Pro SDK and CometChat React UI Kit. You’ve been introduced to the chemistry behind adding mentions and how the CometChat makes it be easy to build.

You have seen how to integrate most of the CometChat functionalities such as texting and real-time messaging. I hope you enjoyed this tutorial and that you were able to successfully in adding mentions into your React chat app.

It's time to get busy and build other related applications with the skills you have gotten from this tutorial.

About the Author

Hiep Le is a full-time software engineer who takes a huge interest in building software products. Most of his work is focused on one thing - to help people learn.

Hiep Le

CometChat

Hiep Le is a software engineer. He takes a huge interest in building software products and is a full-time software engineer. Most of his work is focused on one thing - to help people learn.

Try out CometChat in action

Experience CometChat's messaging with this interactive demo built with CometChat's UI kits and SDKs.