TalkJS is an API that allows you to integrate chat into your web or mobile app. It comes with a pre-built UI, allowing you to get it up and running within minutes. This tutorial will go over how to use TalkJS to create a Next.js chat app.

This guide is for those already familiar with Next.js—and React in general—and have a pre-existing Next.js app. Moreover, the process of authenticating a user and retrieving their details is beyond the scope of this tutorial.

Let’s get started, shall we?

Getting ready

We will be building a basic chat component which will allow a user on our site to initiate conversations with other users.

First, let’s add TalkJS to our project.

# NPM
npm install talkjs --save

# Yarn
yarn add talkjs

With that done, we’ll import it into our component.

import Talk from 'talkjs';

To ensure that the following code runs after the page has finished loading, we will wrap it within a useEffect hook. If you’re using React class components, you would use componentDidMount instead. We will then use the ready promise of the Talk object to check if the TalkJS script has loaded.

import { useEffect } from 'react';

export default function Chat() {
  useEffect(() => {
    Talk.ready.then(() => {
      // rest of the code goes here
    });
  }, []);
}

We should also create a reference outside useEffect and link it to one of the elements our component will render. This is where the chat window will be loaded once everything is ready.

import { useEffect, useRef } from 'react';

// ...
const chatboxEl = useRef();

// ...
return (
  <main>
    <div ref={chatboxEl} />
  </main>
)

Now we’re ready to add in the meat of the component.

Creating a session

A session represents a connection between a user’s browser tab and TalkJS. It logs them in and authenticates your app, and ends once the user has navigated away from the page.

Let’s create a Session and pass our appId and a user to it. This, and the rest of the code in the succeeding sections, will also be placed inside this hook—and within Talk.ready.then—unless stated otherwise.

useEffect(() => {
  Talk.ready.then(() => {
    const session = new Talk.Session({
      appId: 'YOUR_APP_ID',
      me: currentUser,
    });
  });
}, []);

You can find the app ID in your TalkJS dashboard. We will create the user in the next section.

Creating users

The current user—denoted by me in the session above and the variable currentUser in this tutorial—refers to the user currently logged in to this instance of TalkJS.

Let’s create this User and place it before session.

const currentUser = new Talk.User({
  id: '1632',
  name: 'Kate Smith',
  email: 'katesmith@example.com',
  photoUrl: 'kate.jpeg',
  welcomeMessage: 'Hey there!',
  role: 'default',
});

const session = new Talk.Session({
// ...

Kate can’t possibly talk to herself, so let’s create another user for her to chat to.

const otherUser = new Talk.User({
  id: '1629',
  name: 'Jack White',
  email: 'jackwhite@example.com',
  photoUrl: 'jack.jpeg',
  welcomeMessage: 'Hi, how can I help?',
  role: 'default',
});

In a production environment, you would retrieve the details passed to User above from a database. In the docs you can read more about the data you can include for a TalkJS User / Participant.

Initiating a conversation

We will use the getOrCreateConversation method to initiate a conversation between our two users and then use setParticipant to add them in.

const conversation = session.getOrCreateConversation(
  Talk.oneOnOneId(currentUser, otherUser)
);

conversation.setParticipant(currentUser);
conversation.setParticipant(otherUser);

The oneOnOneId uses the users’ IDs to create a unique ID for the conversation. A conversation that you have created before is fetched instead of created, along with its entire history.

Adding the UI

Now that our conversation is ready, all that’s left is to display it on our page. There are different, customisable UIs available in TalkJS, and the process for adding them is roughly the same. Here, we’ll be using a chatbox.

We will utilise the Session method createChatbox to do just that, after which we can select our conversation and mount the UI onto the reference we created earlier.

const chatbox = session.createChatbox();
chatbox.select(conversation);
chatbox.mount(chatboxEl.current);

Voilà, our chatbox is ready!

Making it content-agnostic

While we have managed to add TalkJS to our app, it isn’t quite useful in a real-world scenario. The biggest issue with it is that it restricts our currentUser to a conversation with one specific person. What if they wanted the ability to choose whom they talk to?

Let’s deconstruct our code to:

  1. launch the chat box at the click of a button;
  2. have different buttons for talking to different users.

Create a new function outside useEffect and pass the other, non-current user to it.

function converse(user) {
  // ...
}

Next, we’ll move the code that was previously within the useEffect hook into the newly-made function. The otherUser’s details will be replaced by the user argument passed to the function.

function converse(user) {
  Talk.ready.then(() => {
    // ...
    const otherUser = new Talk.User(user);
    // ...
  });
}

We’ll move Jack’s details into a new object—outside the function—and create a third user, as well.

const jack = { // ... };

const mary = {
  id: '1596',
  name: 'Mary Hall',
  email: 'maryhall@example.com',
  photoUrl: 'mary.jpeg',
  welcomeMessage: 'Hello, what can I do for you?',
  role: 'default',
};

Remember, these details would normally be fetched from a database and probably passed to our component rather than being stored within it.

Now all we need to do is pass the details of the user we want to talk with to the converse function.

On the click of a button

Let’s add a <section> below the chat window which displays the users we can initiate conversations with.

<section>
  <button onClick={() => converse(jack)}>
    // ...
  </button>
  <button onClick={() => converse(mary)}>
    // ...
  </button>
</section>

As you see above, we have created a <button> for both jack and mary. Clicking on either executes the converse function, passing the relevant user’s object as an argument.

There we have it! Our current user can now initiate a chat with either jack or mary at the click of a button.

Server-side rendering (SSR)

It would be prudent to add a brief note about SSR, a common use-case scenario for Next.js apps. You could fetch all your users at build time using getStaticProps. However, this may be inefficient, and you may want to fetch them on a per-request basis. In that case, it would be necessary to get user details from your database using getServerSideProps, allowing your app to fetch the relevant data on each request.

Concluding remarks

In this tutorial, we’ve gone over the basic concepts involved in an instance of TalkJS, how they relate to each other, and how we can implement them in a Next.js app. Additionally, we have seen how we can make our chat functionality content-agnostic, allowing us to use the same function to initiate conversations with any number of people.

You’ve successfully subscribed to TalkJS
Welcome back! You’ve successfully signed in.
Great! You’ve successfully signed up.
Your link has expired
Success! Check your email for magic link to sign-in.