16 min read
.
on Dec 16, 2020
This tutorial will walk you through the steps to easily build a live support customer widget and a chat dashboard for a support agent using components in React.

One of the most engaging and powerful tools you can have on your website or application is live chat—it’s like you’re standing in the room with your customer and able to help them as soon as they need assistance. With live chat, you’ll be able to improve your user experience, increase your sales conversion rate, and enhance your customers confidence in your support. Modular chat kits, powered by PubNub, offer a solution for the unique needs of live chat for customer support. Our Live Support Chat Kit is optimized for the common needs of a live support widget for customers and provides a comprehensive dashboard for support agents. And since the kit is modular, you can enable and disable components and customize the CSS to meet your needs. 

SupportChat1

This tutorial will walk you through the steps to easily build a live support customer widget and a chat dashboard for a support agent using components in React. With React, you can tweak and arrange the many UI objects that make up an application using just a few components. These components enable you to quickly and effortlessly customize the support chat experience to your needs with a lot of flexibility. 

The components for our Live Support Chat kit are built to be expandable, reusable, and flexible for integration into another React application. You can modify the open source chat components by editing their CSS and layout to your specifications. This tutorial simply serves as a template of how to build a straightforward, but winning, live chat solution, but feel free to use it as a starting off point for your application and customize as you see fit and as fits your use case. 

SupportChat2

What backend API works best for live support chat?

Before you jump into building your live support chat, consider how your messages will be transmitted—this will guide which API provider is the best choice for you. The components we’ll be going over in this post are an example of how to integrate open source React chat components with PubNub to power all chat features. In the tutorial in this article, PubNub is used for presence indicators, reliable messaging delivery, and other chat related data to enable the front end React components to update live as messages are received and users come online.

PubNub is a perfect fit for powering support chat applications because it’s adaptable to the needs of any application that can benefit from real-time messaging.

Some key reasons to use PubNub:

  • User Presence is built-in, so you can easily create online and offline indicators for managing multiple chats with users.

  • PubNub delivers billions of messages every day, so your chat will work at any scale.

  • Storage and Playback is available for message history, which means agents can jump right into a conversation or ticket, armed with the history from previous chats.

  • Push Notifications support is included, which can power alerts to users of new replies on mobile apps—like if a support agent weighs in on a ticket when the user is out of your app. 

And the best part of building with PubNub? You don’t need prior experience with PubNub or PubNub SDKs to use these React chat components. The components explained in this tutorial are already fully integrated with PubNub, and this tutorial will explain exactly how PubNub works with each chat component so you’ll have a clear understanding of how to build your live support chat. 

Learning React and Typescript

Now that you’re familiar with PubNub and the benefits of selecting us as your API provider, let’s review React and Typescript. React is a popular framework used by developers to develop modern web apps. TypeScript is a type safe language built on top of Javascript. TypeScript offers more functionality over Javascript and is the current standard in the React world.

But don’t worry, you can still follow this guide if you’re not familiar with React or Typescript. All the steps and contextual information you need to use the Live Support Chat Kit with open source React chat app components is included in this article.

If you’d like more information on React before you start building your live support chat, the Learn React Guide from PubNub docs is a great way to get started with React. Also consider React Overview and Walkthrough by Tania Rascia if you’re looking for a comprehensive guide to React in detail. 

Typescript provides a type system for type checking, refactoring, additional navigation features, and more. For a complete review of the benefits of using Typescript with React, check out the post Getting Started with React and TypeScript.

React development environment set up

Before you get started using PubNub for your chat backend, you must first configure the tools needed to build a customer support chat application in React. Here’s how: 

How to set up your Node.js development environment

To start building with PubNub and our React components, you first need to install Node.js.

If you’ve already installed Node.js, you can go to the next section.

If you don’t have Node.js installed, visit the Node.js Downloads page and select the installer for your platform.

Open your terminal and run the following commands to check the installation:

node -v
npm -v

You should see a version number after you run these commands. 

How to set up your Git

To clone the React project for this tutorial from GitHub you need Git installed.

If you’ve already installed Git, you can go to the next section.

To install Git, follow the Getting Started - Installing Git guide to install or update Git.

Open your terminal and run the following command to check the installation:

git --version

You should see a version number after you run the command. 

Setting up a backend for support chat app components 

Now that your development environment is set up, but before we begin building, let’s set up the backend that we’ll use with our support chat components. Once you complete these steps, you will have two API keys that you’ll use in the React-based Live Support Chat Kit—the API keys and your PubNub account are free.

To set up your backend:

  1. Sign up for a PubNub account.

  2. Go to your PubNub Dashboard.

  3. Click Create New App.

  4. Give your app a name, and select Chat App as the app type.

  5. Click Create.

  6. Click your new app to open its settings, then click its keyset.

  7. Enable the Channel Presence feature for your keyset.

  8. Enable the Storage and Playback feature for your keyset. 

  9. Enable the Stream Controller feature for your keyset.

  10. Save the changes.

  11. Copy the Publish and Subscribe keys for the next steps.

Building and running a support chat app with React

Now that you have your PubNub API keys, you can start building your live support chat with our Live Support Chat Kit components.

To start this tutorial, open your terminal and clone the Live Support Chat Kit repository below. This repo contains the PubNub powered, open-source chat components and chat UI necessary to build a live support chat solution. And remember, all of the components and their UI are customizable.

git clone https://github.com/PubNubDevelopers/chat-component-app-live-support.git

There are two projects in the repo: the Support Chat Dashboard and the Customer Chat Widget. The Support Chat Dashboard gives support agents a place to see customers that are online and chat with them. The Customer Chat Widget offers an easy way for users to interact with support agents.

Let’s dive into how to build and run both of these projects: 

Building and running the support chat dashboard

To create your live support dashboard, navigate into the repository with your terminal. The support chat dashboard can be tested and run from this location.

cd /chat-component-app-live-support/support-agent-dashboard

Next, configure the components with the API keys obtained from your PubNub dashboard. Your API keys allow you to send and receive messages on the PubNub network. 

Open the file src/config/pubnub-keys.json and replace YOUR_PUBLISH_KEY_HERE and YOUR_SUBSCRIBE_KEY_HERE with your API keys.

The Node module dependencies used by the chat components need to be installed. This process takes a few minutes to download and install the dependencies with npm.

npm install

Now you can run the project. 

npm start

The Support Chat Dashboard should now open at http://localhost:8080, but to test it out you’ll need to start a Customer Chat Widget.

Building and running the customer chat widget

To create your customer-facing widget, navigate into the repository with your terminal. The Customer Chat Widget can be tested and run from this location. 

cd /chat-component-app-live-support/support-client-widget

Next, configure the components with the API keys obtained from your PubNub dashboard. Your API keys allow you to send and receive messages on the PubNub network. 

Open the file src/config/pubnub-keys.json and replace YOUR_PUBLISH_KEY_HERE and YOUR_SUBSCRIBE_KEY_HERE with your API keys. Make sure to use the same API keys you used for the Support Agent Dashboard.

Now, the Node module dependencies used by the Customer Chat Widget components need to be installed. This process takes a few minutes to download and install the dependencies with npm.

npm install

Now you can run the project and try out each of the components. 

npm start

The Customer Chat Widget should now open at http://localhost:8081.

Testing customer support real-time chat

When the Customer Chat Widget React app opened you should have immediately seen a new active user appear in the Support Agent Dashboard. If you refresh the Customer Chat widget or open it in more windows you’ll see more users show up in the active users list on the Support Agent Dashboard. Based on the settings you’ve configured in your PubNub dashboard, these users will disappear after you close the Customer Chat Widget windows

Try selecting a name in the active users list to open a chat in the Support Agent Dashboard. Put text in the text area and press enter. You should see your message appear in the message list area in both the Support Agent Dashboard and the Customer Chat Widget. You can respond from the Customer Chat Widget and also see the messages in the Support Agent Dashboard. 

Support chat component structure 

Now that you’ve tried out and tested the Customer Support Chat Kit components, let’s review the component structure of each UI view. The Support Agent Dashboard and the Client Chat Widget have a slightly different component structure. However, in both applications the components work together to create a complete chat experience. The components allow you to easily customize them and expand on them for more functionality. 

Support Agent Dashboard structure

  • Active Users: This component displays a list of the active users that have Customer Chat Widgets open. This uses PubNub Presence events to maintain the list of chats. 

  • Message List: This component displays the messages received in the chat and any chat history when a new chat is selected.

  • Compose: This component provides a text input area for composing new messages to send to the chat. The corresponding Customer Chat Widget will receive the message.  

Customer Chat Widget structure

  • Message List: This component displays the messages received from the agent.

  • Compose: This component provides a text input area for composing new messages to send to the chat. The Support Agent Dashboard will receive the message.

Support chat components explained

By this point, you should have an idea of how the components work together to drive both sides of the conversation after demoing both of the Support Chat Kit UI views. Let’s further break down how the components work and how you can customize them. 

Component alignment 

Some components are primarily used to align the functional chat components. These components are:

ChatDemo:

In both UI views this is used to outline the structure of the majority of the application. If you open the file src/components/ChatDemo/ChatDemo.tsx in either UI view you’ll find the component structure. Notice how in the Support Agent Dashboard there are two main sides to this chat application and in the Client Chat Widget there is only one.

Support Agent Dashboard:

    <ChatDemoWrapper>
      <ActiveUsersListPanelWrapper>
        <ActiveUsersListPanel />
      </ActiveUsersListPanelWrapper>
      <MessageListPanelWrapper>
        <MessageListPanel />
      </MessageListPanelWrapper>
    </ChatDemoWrapper>

Client Chat Widget:

  <ChatDemoWrapper>
      <MessageListPanelWrapper>
        <MessageListPanel />
      </MessageListPanelWrapper>
    </ChatDemoWrapper>

MessageListPanel:

For both UI views this component provides the alignment for the MessageList component and the compose text area. Open the file for either UI view at src/components/MessageListPanel/MessageListPanel.tsx and you’ll find the component structure (it’s the same for both).

      <MessageList />
      <ComposeMessageBoxWrapper>
        <UserImgWrapper src={state.selfAvatar} />
        <TextInputWrapper>
          <SendMessageField />
        </TextInputWrapper>
      </ComposeMessageBoxWrapper>

The MessageListPanel component has an area to display the current user avatar. The avatar url is created in the src/AppStateContext.tsx file when the initial state is defined. It’s set from the name created by the generatedName() function for the Customer Chat Widget. The Support Agent Dashboard always uses the name “Support Agent” so the avatar always stays the same. Consider the avatar URL a placeholder for where you can set custom avatars or use a service like Gravatar for avatars.

 selfAvatar: "https://ui-avatars.com/api/?name="+generatedName+"?size=100&rounded=true&uppercase=true&bold=true&background=edab63&color=FFF", //The img for the avatar graphic file
  selfName: generatedName, // Set the display name.

ActiveUsersListPanel:

Only for the Support Agent Dashboard. This component aligns the ActiveUsersList component.

Compose component

Both compose components can be found in the src/components/ComposeMessageBox directory for either view. Open the file ComposeMessageBox.tsx and you’ll see the compose component returns a text area.

<SendMessageField></SendMessageField>

A function for handling key press events dispatches the SEND_MESSAGE function declared in the src/AppStateContext.tsx file for both views. 

const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      dispatch({
        type: 'SEND_MESSAGE',
        payload: textAreaEl.current.value,
      })
      textAreaEl.current.value = ''
    }
  }

The SEND_MESSAGE function publishes the contents of the input field to the active channel. This is publishing a chat message. In this app the Customer Client Widget publishes messages to a channel name based on the user's generated name. The active channel for the Support Agent Dashboard is determined by the last user selected in the active users panel (it must be selected first). The sender’s name is also appended to the published message.

Support Agent Dashboard:

    // Publishes a message to chat channel.
    case "SEND_MESSAGE": {

      if (state.activeChannel == "") {
        alert("Select a conversation from the user list first to send messages.");
      } else {
        state.pubnub.publish({
          channel: state.activeChannel,
          message: {
            "message": DOMPurify.sanitize(action.payload as string) as string, 
            "senderName": state.selfName as string,
          },
        });
      }
      return { ...state }
    }

Client Chat Widget:

  // Publishes a message to the chat channel.
    case "SEND_MESSAGE": {

      state.pubnub.publish({
        channel: state.activeChannel,
        message: {
          "message": DOMPurify.sanitize(action.payload as string) as string,
          "senderName": state.selfName as string,
        },
      });

      return { ...state }
    }

User Presence Component

The Support Agent Dashboard has an active users component that’s found in the src/components/ActiveUsersList directory. Open the file ActiveUsersList.tsx. You’ll see that the component returns a list from the UUIDs in the state.activeUsers array. The active users component also shows a count of the current occupancy in the header of the list. The UUID for a user is configured to the same as the generated name for each user and as a result you don’t need any additional information to visually display who a user is (so there’s no API lookup).

const ActiveUsers = Array.from(state.activeUsers).map((activeUserName: string, i: number) => {
    return (
      <React.Fragment key={i}>
        <ActiveUser activeUser={activeUserName} />
        <div ref={activeUserEndRef} />
      </React.Fragment>
    );
  });

  return <><ActiveUsersHeader>Active 
Users<ActiveUsersOccupancy>{state.presenceOccupancy}</ActiveUsersOccupancy></ActiveUsersHeader><ActiveUsersListWrapper>{ActiveUsers}</ActiveUsersListWrapper></>

The ActiveUser sub component is found in the src/components/ActiveUser directory. Open the file ActiveUser.tsx. If the user being listed is selected by the agent the name will be highlighted in the list. Each user name is displayed with an avatar generated from the user’s name.

const ActiveAvatarURL = "https://ui-avatars.com/api/?name="+props.activeUser+"?size=100&rounded=true&uppercase=true&bold=true&background=5EB977&color=FFF";
    
    const handleChannelChange = (event) => {
        dispatch({
            type: 'CHANGE_CHANNEL',
            payload: props.activeUser,
        })
    }

    if ("support."+props.activeUser == state.activeChannel) {
        return (
            <ActiveUserWrapperSelected onClick={handleChannelChange}>
                <ActiveUserAvatarWrapper src={ActiveAvatarURL} />
                <ActiveUserNameWrapper>{props.activeUser}</ActiveUserNameWrapper>
            </ActiveUserWrapperSelected>
        )
    }
    return (
        <ActiveUserWrapper onClick={handleChannelChange}>
            <ActiveUserAvatarWrapper src={ActiveAvatarURL} />
            <ActiveUserNameWrapper>{props.activeUser}</ActiveUserNameWrapper>
        </ActiveUserWrapper>
    )

When a user is selected in the list the “CHANGE_CHANNEL” function is dispatched. The “CHANGE_CHANNEL” function updates the state.messages array in src/AppStateContext.tsx with the history of messages for that user. This way if a user is messaging before the agent has the chat open they can still see the messages. If there are no messages then an alert message shows to let the agent know to start the conversation.

 //Change activeChannel and get history for the new channel.
    case "CHANGE_CHANNEL": {
      if (state.activeChannel != "support."+action.payload) {

        var historyMessages: Array<string> = [];

        state.pubnub.history(
          {
              channel: state.channel+"."+action.payload,
              count: state.historyMax // Limit of 100 messages.
          },
          (status, response) => { 
            if (typeof response.messages !== "undefined" && response.messages.length > 0) {
              for (var i = 0; i <= response.messages.length; i++) {
                if (typeof response.messages[i] !== "undefined") {
                  historyMessages.push(response.messages[i].entry);
                }
              }
            } else {
              historyMessages.push({
                message: "Send a message to "+action.payload+" to start the conversation.",
                senderName: "Support Dashboard Alert",
                userAvatar: "https://ui-avatars.com/api/?name=Support+Dashboard?size=100&rounded=true&uppercase=true&bold=true&background=FB0106&color=FFF"
              });
            }
          }
        );

        const changeChannelState: AppState = {
          ...state,
          messages: historyMessages,
          activeChannel: state.channel+"."+action.payload
        };

        return changeChannelState; 
      }
      return { ...state }
    }

The src/AppStateContext.tsx file manages the state.activeUsers array. When the application is started a hereNow call is made to PubNub for the global channel occupants. The support agent is not added to the list, since the agent does not need to chat with themselves.

 state.pubnub.hereNow(
          {
              channels: [state.channel],
              includeUUIDs: true // In this demo we're using the uuid as the user's name. You could also use presence state to provide a username and more. In this app all we need is the UUID of online users.
          },
          (status, response) => {
            if (response.channels[state.channel].occupancy > 0) {
              for (var i = 0; i < response.channels[state.channel].occupancy; i++) {
                if ((!state.activeUsers.includes(response.channels[state.channel].occupants[i].uuid)) && (response.channels[state.channel].occupants[i].uuid !== state.selfName)) {
                  newActiveUsers.push(response.channels[state.channel].occupants[i].uuid); 
                }
              }
              newActiveUsers.sort();
              dispatch({
                type: "REFRESH_ACTIVEUSERS",
                payload: newActiveUsers
              });
              dispatch({
                type: "UPDATE_OCCUPANCY",
                payload: newActiveUsers.length
              });
            }
          }
        );

The “REFRESH_ACTIVEUSERS” function refreshes the state.activeUsers array with the new list of users. The “UPDATE_OCCUPANCY” function updates the count of state.presenceOccupancy. 

    //REFRESH_ACTIVEUSERS replaces array of users in our internal activeUsers buffer.
    case "REFRESH_ACTIVEUSERS": {
       const activeUsersList: AppState = {
        ...state,
        activeUsers: [
          ...action.payload as Array<string>
        ]
      };
      return activeUsersList;
    }
    //UPDATE_OCCUPANCY updates the current count of users
    case "UPDATE_OCCUPANCY": {

      const occupantsUpdate: AppState = {
        ...state,
        presenceOccupancy: action.payload as string
      };

      return occupantsUpdate;
    }

When users open and close the Customer Chat Widget the list of active users is updated by a PubNub listener callback (the same one used for new messages) in the Support Agent Dashboard.

presence: function(p) {
          if (p.action == "join") {
            if ((!state.activeUsers.includes(p.uuid)) ) { // Only add users if they are missing from the list.
              newActiveUsers.push(p.uuid); 
              newActiveUsers.sort();
              dispatch({
                type: "REFRESH_ACTIVEUSERS",
                payload: newActiveUsers
              });
              dispatch({
                type: "UPDATE_OCCUPANCY",
                payload: newActiveUsers.length
              });
              // Add to current count 
            }
          }
          if ((p.action == "timeout") || (p.action == "leave")) {
            var index = newActiveUsers.indexOf(p.uuid)
            if (index !== -1) {
              newActiveUsers.splice(index, 1);
              dispatch({
                type: "REFRESH_ACTIVEUSERS",
                payload: newActiveUsers
              });
              dispatch({
                type: "UPDATE_OCCUPANCY",
                payload: newActiveUsers.length
              });
            }
          }
        }

Message List component

The message list component is located in the src/components/MessageList directory for both chat UI views. Open the file MessageList.tsx. You’ll see that the message list component returns the list of messages from the state.messages array. This component is the same for both UI views.

export const MessageList: React.SFC<MessageListProps> = (props: MessageListProps) => {
  const { state } = useAppState();
  const [stopOnScroll, setStopOnScroll] = useState(false);
  const messagesEndRef = useRef<null | HTMLDivElement>(null)
  const scrollToBottom = () => {
   messagesEndRef?.current?.scrollIntoView({ block: "end", inline: "nearest", behavior: "smooth" });
    }

  useScrollPosition(({ prevPos, currPos }) => {
     const isShow = currPos.y > prevPos.y
    if (isShow !== stopOnScroll) setStopOnScroll(isShow)
  }, [])

  useEffect(scrollToBottom, [state.messages])

  const Messages = Array.from(state.messages).map((onemessage: Array<any>, i: number) => {
    return (
      <React.Fragment key={i}>
        <Message message={onemessage} />
        <div ref={messagesEndRef} />
      </React.Fragment>
    );
  });

  return <MessageListWrapper>{Messages}</MessageListWrapper>
}

The Message subcomponent is located in the src/components/Message directory for both chat UI views. Open the file Message.tsx. You’ll see that messages are conditionally formatted depending on if you sent or received the message. Each message is formatted with an avatar (generated from the message sender name), the sender name, and the actual message. The message subcomponent for the Support Agent Dashboard is slightly different to enable alerts to help the agent use the dashboard.

Support Agent Dashboard:

if (props.message.senderName == state.selfName) { // Display messages from yourself on the right.
      const userAvatar = "https://ui-avatars.com/api/?name="+props.message.senderName+"?size=100&rounded=true&uppercase=true&bold=true&background=edab63&color=FFF";
      return (
            <MessageWrapper key={props.message.internalKey}>
                <RightWrapper>
                    <SenderNameWrapperSelf>{props.message.senderName}</SenderNameWrapperSelf>
                    <AvatarWrapperSelf src={userAvatar} />
                </RightWrapper>
                 <MessageMessageWrapperSelf><MessageMessageInnerWrapperSelf>{props.message.message}</MessageMessageInnerWrapperSelf></MessageMessageWrapperSelf>
            </MessageWrapper>
        )
    } else {
        let userAvatar = "https://ui-avatars.com/api/?name="+props.message.senderName+"?size=100&rounded=true&uppercase=true&bold=true&background=5EB977&color=FFF";
        if (props.message.senderName == "Support Dashboard Alert"){ // Use red for alerts
            userAvatar = "https://ui-avatars.com/api/?name=Support+Dashboard?size=100&rounded=true&uppercase=true&bold=true&background=FF6B56&color=FFF";
        }
        return (
            <MessageWrapper key={props.message.internalKey}>
                <AvatarWrapper src={userAvatar} />
                <SenderNameWrapper>{props.message.senderName}</SenderNameWrapper>
                <MessageMessageWrapper><MessageMessageInnerWrapper>{props.message.message}</MessageMessageInnerWrapper></MessageMessageWrapper>
            </MessageWrapper>
        )
    }

Customer Chat Widget:

if (props.message.senderName == state.selfName) { // Display messages from yourself on the right.
        const userAvatar = "https://ui-avatars.com/api/?name="+props.message.senderName+"?size=100&rounded=true&uppercase=true&bold=true&background=edab63&color=FFF"
        return (
            <MessageWrapper key={props.message.internalKey}>
                <RightWrapper>
                    <SenderNameWrapperSelf>{props.message.senderName}</SenderNameWrapperSelf>
                    <AvatarWrapperSelf src={userAvatar} />
                </RightWrapper>
                <MessageMessageWrapperSelf><MessageMessageInnerWrapperSelf>{props.message.message}</MessageMessageInnerWrapperSelf></MessageMessageWrapperSelf>
            </MessageWrapper>
        )
    } else {
        const userAvatar = "https://ui-avatars.com/api/?name="+props.message.senderName+"?size=100&rounded=true&uppercase=true&bold=true&background=5EB977&color=FFF"
        return (
            <MessageWrapper key={props.message.internalKey}>
                <AvatarWrapper src={userAvatar} />
                <SenderNameWrapper>{props.message.senderName}</SenderNameWrapper>
                <MessageMessageWrapper><MessageMessageInnerWrapper>{props.message.message}</MessageMessageInnerWrapper></MessageMessageWrapper>
            </MessageWrapper>
        )
    }

The state.messages array is managed by the src/AppStateContext.tsx file for both chat UI views. When the application starts a subscription for messages begins. In the Customer Chat Widget the subscription is for the global support channel (“support”) and an active channel set to “support.[generated name]”. In the Support Agent Dashboard the subscription is for the global support channel (“support”) and the global channel + wildcard (“support.*”). The subscription for the global support channel “support” is only used for application wide presence and not for sending and receiving messages.

Support Agent Dashboard:

 // Subscribe on the default channel.
      state.pubnub.subscribe(
        {
          channels: [state.channel, state.channel+".*"], // Subscribe to global channel for presence events and to the wildcard for chat messages.
          withPresence: state.presence, 
        }
      );

Customer Chat Widget:

  // Subscribe on the default channel.
      state.pubnub.subscribe(
        {
          channels: [state.channel, state.activeChannel], // Subscribe to both the global and active channel.
          withPresence: state.presence, 
        }
      );

New messages from the subscription are received by the PubNub listener callback. The Support Agent Dashboard also filters messages and only displays messages received from the currently active chat/channel.

Support Agent Dashboard:

 state.pubnub.addListener({
        message: (messageEvent) => {
          messageEvent.message.message = DOMPurify.sanitize(messageEvent.message.message as string) as string;
          if (messageEvent.channel == state.activeChannel) { // Only add messages sent to activeChannel
            dispatch({
              type: "ADD_MESSAGE",
              payload: messageEvent.message
            });
          }
        },
    	});

Customer Chat Widget:

state.pubnub.addListener({
        message: (messageEvent) => {
          messageEvent.message.message = DOMPurify.sanitize(messageEvent.message.message as string) as string;
          dispatch({
            type: "ADD_MESSAGE",
            payload: messageEvent.message
          });
        },
});

Messages are appended to the message list array with the ADD_MESSAGE function. The ADD_MESSAGE function adds the new message to the start of the array and discards old messages.

//ADD_MESSAGE adds an incoming message to our internal MessageList buffer.
    case "ADD_MESSAGE": {
      //If the message list is over our cap we discard the oldest message in the list.
      if (state.messages.length > state.maxMessagesInList ){
        state.messages.shift();
      }

      const addMessage: AppState = {
        ...state,
        messages: [
          ...state.messages as Array<string>,
          {
            ...action.payload as Array<string>
          }
        ]
      };

      return addMessage;
    }

Adding more features to your support chat app

Live Support Chat

Live support chat lets you quickly resolve issues for your customers.

With these open-source chat components you can build a chat support solution for any purpose. These components are all expandable with more features and you can customize the CSS. Consider these components as a template and you’ll easily be able to use the Live Support Chat Kit with your application to improve user engagement and sales conversion.

Some other awesome chat features you can include with PubNub:

Building a live support chat app? Get in touch with our sales team to quickly get your in-app chat up and running.

More From PubNub