DEV Community

Cover image for In-App chat in react.js with ZEGOCLOUD
Zain Ahmed
Zain Ahmed

Posted on

In-App chat in react.js with ZEGOCLOUD

Almost any developer create a Chat Application in their initial career as a showcase project. I also did when I start learning about MERN Stack & I build chat app in with 2 different tech, Firebase with React.js & Socket.io (Node.js) with React.js.

As we grow in over experience we learn that thing can be done more easily and quickly by taking some help from pre build libraries instead of creating it custom.

Here is another feature of ZEGOCLOUD called In-App chatting which love it, it just take a small configuration and chunk of code and your life can be easy.

What I build

I have build a basic one-to-one chatting app using ZEGOCLOUD

Tech Stack

React.js (Frontend)

Configuration

  1. Go to ZEGOCLOUD and make a account
  2. Go to dashboard and create a APP

step-

  1. Select In-app chatting feature
  2. Go to Service Management option from dashboard and select In-App chatting feature

step-

  1. Active it

step-

  1. Copy and save AppID for later use
  2. Create a React.JS app using create-reat-app or any React framework.
  3. Create a component for chatting/messaging

Application work flow

  1. install zego-zim-web package in React.js and define AppID which you copy earlier

step-

import React, { useEffect, useState } from 'react';
import { ZIM } from 'zego-zim-web';

var appID = 1423906504;
ZIM.create({ appID });
var zim = ZIM.getInstance();

function Chatting(props) {

    const [toUserId, setToUserId] = useState('')
    const [token, setToken] = useState('')
    const [userId, setUserId] = useState('')
    const [userName, setUserName] = useState('')

return (
        <div className='p-5 flex flex-col'>

            <label className='p-2 font-bold'>Token</label>
            <input className='border p-2 m-2' value={token} onChange={(e) => setToken(e.target.value)} />

            <label className='p-2 font-bold'>Your name</label>
            <input className='border p-2 m-2' value={userName} onChange={(e) => setUserName(e.target.value)} />

            <label className='p-2 font-bold'>UserId</label>
            <input className='border p-2 m-2' value={userId} onChange={(e) => setUserId(e.target.value)} />

            <button className='border p-2 m-2' onClick={handleLogin}>Login</button>

            <label className='p-2 font-bold'>Other person User Id </label>
            <input className='border p-2 m-2' value={toUserId} onChange={(e) => setToUserId(e.target.value)} />

            <button className='border p-2 m-2' onClick={handleSendMessage}>Send Message</button>

        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

I also define some other states for later use

  1. Both user need to generate token from dashboard with unique *userID * save the taken for later use in frontend (the token can be auto generate from backend, If you are using any backend service).

  2. After input userID and Token click login button and it will create a room for user

step-

  1. Once the User enter in room User can send message and can receive message from other user.

  2. There are some event listeners which will help to indicate constantly whether the connection is stable or not also the receive event listener will constantly listen if any new message emit from any other user or not.

  useEffect(() => {
        // Set up and listen for the callback for receiving error codes. 
        zim.on('error', function (zim, errorInfo) {
            console.log('error', errorInfo.code, errorInfo.message);
        });

        // Set up and listen for the callback for connection status changes.
        zim.on('connectionStateChanged', function (zim, { state, event, extendedData }) {
            console.log('connectionStateChanged', state, event, extendedData);
            // When SDK logout occurred due to a long-time network disconnection, you will need to log in again. 
            if (state === 0 && event === 3) {
                zim.login({ userName }, token)
            }
        });

        // Set up and listen for the callback for receiving one-to-one messages. 
        zim.on('receivePeerMessage', function (zim, { messageList, fromConversationID }) {
            console.log('receivePeerMessage', messageList, fromConversationID);
        });

        // Set up and listen for the callback for token expires.
        zim.on('tokenWillExpire', function (zim, { second }) {
            console.log('tokenWillExpire', second);
            // You can call the renewToken method to renew the token. 
            // To generate a new Token, refer to the Prerequisites.
            zim.renewToken(token)
                .then(function ({ token }) {
                    // Renewed successfully.
                })
                .catch(function (err) {
                    // Renew failed.
                })
        });

        zim.on('receivePeerMessage', function (zim, { messageList, fromConversationID }) {
            console.log('receivePeerMessage', messageList, fromConversationID);
        });
    }, [])

Enter fullscreen mode Exit fullscreen mode

As I define some event listeners for some Realtime work, To get current connect state, To get runtime message emit/receive, TO get is token expire and to get error if any.
Here is final component for one-to-one chatting app

import React, { useEffect, useState } from 'react';
import { ZIM } from 'zego-zim-web';

var appID = 1423906504;
ZIM.create({ appID });
var zim = ZIM.getInstance();

function Chatting(props) {

    const [toUserId, setToUserId] = useState('')
    const [token, setToken] = useState('')
    const [userId, setUserId] = useState('')
    const [userName, setUserName] = useState('')


    useEffect(() => {
        // Set up and listen for the callback for receiving error codes. 
        zim.on('error', function (zim, errorInfo) {
            console.log('error', errorInfo.code, errorInfo.message);
        });

        // Set up and listen for the callback for connection status changes.
        zim.on('connectionStateChanged', function (zim, { state, event, extendedData }) {
            console.log('connectionStateChanged', state, event, extendedData);
            // When SDK logout occurred due to a long-time network disconnection, you will need to log in again. 
            if (state === 0 && event === 3) {
                zim.login({ userName }, token)
            }
        });

        // Set up and listen for the callback for receiving one-to-one messages. 
        zim.on('receivePeerMessage', function (zim, { messageList, fromConversationID }) {
            console.log('receivePeerMessage', messageList, fromConversationID);
        });

        // Set up and listen for the callback for token expires.
        zim.on('tokenWillExpire', function (zim, { second }) {
            console.log('tokenWillExpire', second);
            // You can call the renewToken method to renew the token. 
            // To generate a new Token, refer to the Prerequisites.
            zim.renewToken(token)
                .then(function ({ token }) {
                    // Renewed successfully.
                })
                .catch(function (err) {
                    // Renew failed.
                })
        });

        zim.on('receivePeerMessage', function (zim, { messageList, fromConversationID }) {
            console.log('receivePeerMessage', messageList, fromConversationID);
        });
    }, [])


    const handleLogin = () => {
        try {
            const newUserDetails = { userName, userID: userId }
            zim.login(newUserDetails, token)
                .then(function (res) {
                    console.log("res", res)
                })
                .catch(function (err) {
                    console.log("err", err)
                });
        } catch (error) {
            console.log("error", error)
        }
    }

    const handleSendMessage = () => {
        try {
            var toUserID = toUserId;
            var config = {
                priority: 1 // Set priority for the message. 1: Low (by default). 2: Medium. 3: High.
            };

            // Send one-to-one text messages. 
            var messageTextObj = { type: 1, message: `user to ${toUserID} ` };
            zim.sendMessage(messageTextObj, toUserID, 0, config)
                .then(function ({ message }) {
                    console.log("message", message)
                })
                .catch(function (err) {
                    console.log("err", err)
                });
        } catch (error) {
            console.log("error", error)
        }
    }

    return (
        <div className='p-5 flex flex-col'>

            <label className='p-2 font-bold'>Token</label>
            <input className='border p-2 m-2' value={token} onChange={(e) => setToken(e.target.value)} />

            <label className='p-2 font-bold'>Your name</label>
            <input className='border p-2 m-2' value={userName} onChange={(e) => setUserName(e.target.value)} />

            <label className='p-2 font-bold'>UserId</label>
            <input className='border p-2 m-2' value={userId} onChange={(e) => setUserId(e.target.value)} />

            <button className='border p-2 m-2' onClick={handleLogin}>Login</button>

            <label className='p-2 font-bold'>Other person User Id </label>
            <input className='border p-2 m-2' value={toUserId} onChange={(e) => setToUserId(e.target.value)} />

            <button className='border p-2 m-2' onClick={handleSendMessage}>Send Message</button>

        </div>
    );
}

export default Chatting;
Enter fullscreen mode Exit fullscreen mode

You can also get sample code in web(JavaScript) from here Sample code for In-App chatting

Documentation here In-App Chatting Documentation

Checkout my YouTube Channel for more content YarCoder

Top comments (0)