In this post, I want to show you how I built a React chat app in a remarkably short amount of time. To implement chat quickly, I sought help from a couple of handy libraries.
To form the chat UI, I used the react-chat-elements open-source chat UI components.
For almost every UI component react-chat-elements has to offer, CometChat has an accompanying back-end function. Combining these libraries will not only allows you to get up and running in a dash but remain completely flexible too.
It feels natural to start with the UI as it will allow you to visualize the app better, and so let’s begin with an introduction to react-chat-elements.
react-chat-elements is an open-source React chat UI component library. It provides numerous chat components out-of-the-box - from necessities like chat bubbles to more advanced features like file pickers. At the time of this writing, these are the available components:
If you’d like to see the front-end code, I have uploaded it to GitHub here.
Now you have a grasp on react-chat-elements and what the demo will look out, let me introduce you to CometChat.
CometChat is a powerful chat platform, which enables you to send and receive messages and other chat-related data in real-time.
In my case, we I took advantage of the authentication and messaging functions. The authentication function was used to allow the user to login and the messaging functions were be used to send and receive real-time messages (including message attachments like images).
If you’d like to see the back-end code, I have uploaded it to GitHub here.
Thinking through the project
Let’s try thinking in a way we would do when building a real production-ready app. After we know our tech stack, we will define the features we will implement in our app. Then we will go into more details and describe the React components we will need to have these features working as expected. And in the end, we will build and deploy a demo app, which you will be able to run and play with yourself.
Since this app serves educational purposes only, it will be simple, but still functioning as a real chat app. The main features are:
Login screen — allows successful login or shows an error message when login fails. Utilizes local storage to store usernames.
Chat screen — allows sending and receiving text and media chat messages. It provides a text input and buttons for doing so.
Messages Box — renders the messages that are already sent — shows the images and the files as clickable boxes. When the user clicks on a file, it will download it or open it in a new tab, depending on your browser settings.
Let’s see here how to achieve what we described earlier.
In my case, I have decided to have two components. Both of them, I will manage from the main app entry point — App.js. Also, I will use React Hooks for managing their state and execute side effects. Such side effect would be fetching the message history and scrolling to bottom the chat area. And in the end, I will have a place (file) I called utils, where I put functionality for interacting with the browser local storage.
Login — here is the logic responsible for rendering the login screen, checking for correct username and showing an error, in case the entered username is wrong (i.e. different than superhero1, superhero2 or superhero3, as per CometChat sample users). It utilizes a callback function that is passed from the main App.js component. This callback function then uses methods provided by our chat ‘back-end’ to interact with CometChat API and do the actual login. After success, it fetches the history with all the chat conversations and then records the current username to the local storage.
ChatArea — here is where the main app workflow happens. The users are provided with controls for sending text messages or media files. This component leverages React Hooks for managing the state of the messages, accessing the input for sending new messages (inputRef) and showing/hiding the form for attaching a file. It also uses a library based on PubSub (publish-subscribe) pattern for communicating with the other components. Let me give you a bit more details about this below.
The publish-subscribe pattern is one of the very famous design patterns used in software engineering. It is also one of the ways for achieving nice communication between components in your app.
This is the exact purpose we will be using it for - communicating messages from the chat API to the front end part of the app.
The main idea behind this pattern is that it gives you a means for having a publisher on different topics. For example, think about the type of messages we have. Such topics could be ‘TEXT_MSG’ and ‘MEDIA_MSG’. I have extracted these as constants for easier use in our app. PubSub also gives you what is called a subscriber functionality, or simply a way to subscribe for certain topics. Whenever an event from a topic is triggered, all subscribers are notified and can execute given callback functions. In our case, we will listen for such events when a new message is sent and we will update the conversation history by utilizing another callback function — addMessageCallback. When this is executed, we simply update the state containing all previous messages, by adding the new one.
One detail worth mentioning here is that before updating the messages state with the new message, we amend a property called ‘type’ — from ‘image’ to ‘photo’. We do that due to the way react-chat-elements expect image objects, in order to render them properly in the chat area.
And here is the GitHub repo with the source code.
As with many other applications, here we saw how easy is to use CometChat API to quickly build a rich, modern chat app. In this specific case, we used React and react-chat-elements libraries, which helped for speeding up the development by avoiding the need to build simple components from scratch.
There is plenty of space for improvements.
Perhaps you might try to use some of the rest of the react-chat-elements components. Whatever you decide to use, CometChat APIs would be the backbone you can step on and build your new, shiny chat application.