DEV Community

Cover image for Add text chat to a video call built on React and daily-js
Kimberlee Johnson for Daily

Posted on • Originally published at daily.co

Add text chat to a video call built on React and daily-js

When Paul built a custom video chat app using React and the daily-js library, he used the Daily call object.

The Daily call object is like a direct line to the Daily API. It gives us the finest-grained control over a video call, letting us access its lowest level foundations, like participant video and audio tracks. With that great access comes great flexibility! But, it also means that features like text chat need to be added from scratch.

This post walks you through how to do that!

text chat pops up with knock knock joke gif

What we'll build

We're adding to Paul's demo React video app. When a user clicks to start a call, the app passes a Daily room URL to a new Daily call object, then joins the call. The call object tracks important information about the meeting, like other participants (including their audio and video tracks) and the things they do on the call (e.g. muting their mic or leaving), and provides methods for interacting with the meeting.

We'll use the sendAppMessage method and corresponding "app-message" event to add text chat to the app.

What you'll need to build it

  • Daily account: Sign up for an account if you don’t have one already.
  • Cloned daily-demos/call-object-react Github repository: The fastest way to follow along with this tutorial and get a demo app up and running is to clone this repo.
  • Familiarity with React: In this post we skip over a lot of the code that isn’t related to Daily, so it could be worth brushing up on React and/or hooks [0].

With that, we're ready to start!

Add text chat functionality

Our <Chat> is a form that does a few things with the participant <input>, meaning their chat message. First, via React’s useState hook and our handleChange function, it tracks their input in the component state inputValue.

const [inputValue, setInputValue] = useState('');

const handleChange = (event) => {
   setInputValue(event.target.value);
 };
Enter fullscreen mode Exit fullscreen mode

When a participant sends a message, they call handleSubmit, which broadcasts the message, stored in inputValue to other participants on the call using Daily’s sendAppMessage method.

callObject.sendAppMessage({ message: inputValue }, '*');
Enter fullscreen mode Exit fullscreen mode

handleSubmit also updates the sender’s chatHistory state.

const name = callObject.participants().local.user_name
     ? callObject.participants().local.user_name
     : 'Guest';
   setChatHistory([
     ...chatHistory,
     {
       sender: name,
       message: inputValue,
     },
   ]);
   setInputValue('');
Enter fullscreen mode Exit fullscreen mode

In the return statement, <Chat> maps over every value in chatHistory to display the messages.

{chatHistory.map((entry, index) => (
       <div key={`entry-${index}`} className="messageList">
         <b>{entry.sender}</b>: {entry.message}
       </div>
 ))}
Enter fullscreen mode Exit fullscreen mode

That covers sending messages. Now, we're ready to tackle making sure the app notifies recipients and displays their messages.

Alert participants to new messages

After the Daily sendAppMessage fires, it triggers the Daily “app-message” event. Our handleAppMessage event listener reacts to every "app-message." The handler gets the name of the sender from the Daily call object, and updates recipients’ chat histories using setChatHistory.

const participants = callObject.participants();
     const name = participants[event.fromId].user_name
       ? participants[event.fromId].user_name
       : 'Guest';
     setChatHistory([
       ...chatHistory,
       {
         sender: name,
         message: event.data.message,
       },
     ]);

Enter fullscreen mode Exit fullscreen mode

After updating state, the function calls the props.notification() passed down from the parent Tray.js component to highlight the recipient’s chat icon.

chat icon flashes red and grey

We added that chat icon in Tray.js, where we pass state booleans and controller functions as props to Chat.js that determine whether the icon is highlighted or the chat window should be displayed (if it’s been clicked).

const [displayChat, setChatDisplay] = useState(false);
const [highlightedChat, setChatHighlight] = useState(false);

function toggleChat() {
   setChatDisplay(!displayChat);
   if (highlightedChat) {
     setChatHighlight(!highlightedChat);
   }
 }

function handleNewChat() {
   setChatHighlight(!highlightedChat);
 }

// Relevant component snippets 
<TrayButton
       type={TYPE_CHAT}
       disabled={props.disabled}
       highlighted={highlightedChat}
       onClick={toggleChat}
     />
     <Chat onClickDisplay={displayChat} notification={handleNewChat} />
Enter fullscreen mode Exit fullscreen mode

Want to chat more?

There are so many ways to keep customizing Daily calls. While we hope this post is a good springboard for adding text chat to your video apps, you might be interested in more advanced functionality, like enabling file exchange or a chat history that persists once a call ends. A third-party chat integration would be the best way to do that. Stay tuned for more!

For now, experiment with our repository, and please send feedback our way any time at help@daily.co.

[0] If you’d like to get familiar with React and come back later, check out the many great resources on DEV (like Ali Spittel’s intro), or the React docs for more on hooks.

Top comments (0)