Create call invitation project work like Messenger App using ZegoCloud (ReactJS - step-by-step)
Tags: zegocloud, videocall, reactj, callinvitation
Published: 2023-03-26 09:35:14

Have you ever wanted to [create a call video](https://www.zegocloud.com/blog/build-video-call-with-webrtc) app work like Messenger on Facebook? Pick up some friends, call them, and they will receive a notification. They would accept the call invitation, and you can talk with each other.

In the first place, I think it isn't straightforward to create an app like this because it has many things to set up to do this app. But one day, I learned I don't need to do all the hard work. I found the [ZegoCloud platform](https://www.zegocloud.com/), which provides services for us to create a video, call, or chat application with simple steps. I need a little time to [make my first video call application](https://www.zegocloud.com/product/video-call). And I will show you how in this article, step by step.

Let's do it with the following step.

#### 1. Create video-call-invitation ReactJS project
Using create-react-app (If you do not familiar with create-react-app, you can learn more here [Create React App](https://create-react-app.dev/docs/getting-started))

```
npx create-react-app video-call-invitation
```

Now you have a React project with the following structure: 
![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzvypeljcbltorr1ciff.png)

#### 2. Install the call kit plug-in to your project
You need to cd to the root folder and install the plug-in package

```
 npm i @zegocloud/zego-uikit-prebuilt zego-zim-web --save 
```

![Install ZegoCloud package](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bi72o4iv35w7qtob84af.png)

Change App.js file to this. I import instances from `zego-zim-web` and `@zegocloud/zego-uikit-prebuilt`

```
// App.js
import React from 'react';
import { ZIM } from "zego-zim-web";
import { ZegoUIKitPrebuilt } from '@zegocloud/zego-uikit-prebuilt';

export default function App() {
  return (
    <div>App</div>
  );
}

```

#### 3. Create ZegoCloud account, and set up a project to get appID and ServerSecret:

- You can sign up for 10.000 free mins monthly here: https://bit.ly/3yXsodf
- Sign up with some simple step 
![Signup page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4h3q5pxkdlwowrqfx6a.png)


- After sign up and login, access to console admin of ZegoCloud here: https://console.zegocloud.com/dashboard

![Step to create project in ZegoCloud](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ezt2ce10hhch869k72p.png)

> Image 0: Click to create your project
Image 1: Select Voice & Video Call
Image 2: Scroll down to the bottom and click Next
Image 3: Fill Project name and click Start with UIKits
Image 4: ZegoCloud will create a new project for you and redirect you to this page. You can click on For web to get the guide for Web setting

![Step to get appId and ServerSecret](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/763lw1m7yhn4scd1xawm.png)

> Image 5: This is some config, you can change the config by toggle switch button, then click Save & start to integrate
Image 6: You can try it out with this demo
Image 7: Click on overview in the sidebar to get a list of your project. Click on your project.
Image 8: Now, you can get appId and ServerSecret for the coding project. This is unique to your project, so don't share it with anyone, ok =)).

#### 4. Codinggggg
This is the entire code of App.js file
```
import React, { useEffect, useState, useRef } from "react";
import { ZIM } from "zego-zim-web";
import { ZegoUIKitPrebuilt } from "@zegocloud/zego-uikit-prebuilt";

function randomID(len) {
  let result = "";
  if (result) return result;
  var chars = "12345qwertyuiopasdfgh67890jklmnbvcxzMNBVCZXASDQWERTYHGFUIOLKJP",
    maxPos = chars.length,
    i;
  len = len || 5;
  for (i = 0; i < len; i++) {
    result += chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return result;
}

export default function App() {
  const [userInfo, setUserInfo] = useState({
    userName: "",
    userId: "",
  });
  const [calleeId, setCalleeId] = useState("");
  const zeroCloudInstance = useRef(null);

  async function init() {
    const userId = randomID(5);
    const userName = "user_" + userId;
    setUserInfo({
      userName,
      userId,
    });
    const appID = 62xxxx016;
    const serverSecret = "bead82axxxxxx470404736";

    const KitToken = ZegoUIKitPrebuilt.generateKitTokenForTest(
      appID,
      serverSecret,
      null,
      userId,
      userName
    );

    zeroCloudInstance.current = ZegoUIKitPrebuilt.create(KitToken);
    // add plugin
    zeroCloudInstance.current.addPlugins({ ZIM });
  }

  function handleSend(callType) {
    const callee = calleeId;
    if (!callee) {
      alert("userID cannot be empty!!");
      return;
    }

    // send call invitation
    zeroCloudInstance.current
      .sendCallInvitation({
        callees: [{ userID: callee, userName: "user_" + callee }],
        callType: callType,
        timeout: 60,
      })
      .then((res) => {
        console.warn(res);
        if (res.errorInvitees.length) {
          alert("The user dose not exist or is offline.");
        }
      })
      .catch((err) => {
        console.error(err);
      });
  }

  useEffect(() => {
    init();
  }, []);

  return (
    <div>
      <div>My username: <span>{userInfo.userName}</span></div>
      <div>My userId: <span>{userInfo.userId}</span>
      </div>
      <input
        type="text"
        is="userId"
        placeholder="callee's userID"
        onChange={(event) => {
          setCalleeId(event.target.value);
        }}
      />
      <button
        onClick={() => {
          handleSend(ZegoUIKitPrebuilt.InvitationTypeVideoCall);
        }}
      >
        Video call
      </button>
      <button
        onClick={() => {
          handleSend(ZegoUIKitPrebuilt.InvitationTypeVoiceCall);
        }}
      >
        Voice call
      </button>
    </div>
  );
}
```

Let me explain it:

- function randomID(len) used to generate random userId, because it user adds to room need have unique userId
```
  const [userInfo, setUserInfo] = useState({
    userName: "",
    userId: "",
  });
  const [calleeId, setCalleeId] = useState("");
  const zeroCloudInstance = useRef(null);
```
- userInfo used to store userName and userId
- calleeId store calleeId, which it will send invitations to.
- zeroCloudInstance using to store ZeroCloud variable used to access API from ZegoUIKitPrebuilt


```
  async function init() {
    const userId = randomID(5);
    const userName = "user_" + userId;
    setUserInfo({
      userName,
      userId,
    });
    const appID = 62xxxx016;
    const serverSecret = "bead82a3061xxxxxxx70404736";

    const KitToken = ZegoUIKitPrebuilt.generateKitTokenForTest(
      appID,
      serverSecret,
      null,
      userId,
      userName
    );

    zeroCloudInstance.current = ZegoUIKitPrebuilt.create(KitToken);
    // add plugin
    zeroCloudInstance.current.addPlugins({ ZIM });
  }

  useEffect(() => {
    init();
  }, []);
```

- init function used to init variable, it is called from useEffect hook. It inits userId, userName. It uses the generateKitTokenForTest function from ZegoUIKitPrebuilt to create a token to access the server from Zegocloud. It passes the following params - the name shows itself 

```
(appID, serverSecret, null, userId, userName)
```
Except for null value, it is roomId value. Because this is called invitation, so we leave null.

- ZIM is a call invitation plugin, so we need to add it so we can use the function of call invitation
```
zeroCloudInstance.current.addPlugins({ ZIM });
```

- function handleSend use to send call invitations to callee users. It receives callType. We use two call types here: ZegoUIKitPrebuilt.InvitationTypeVideoCall (for Video) and ZegoUIKitPrebuilt.InvitationTypeVoiceCall (for voice).

```
  function handleSend(callType) {
    const callee = calleeId;
    if (!callee) {
      alert("userID cannot be empty!!");
      return;
    }

    // send call invitation
    zeroCloudInstance.current
      .sendCallInvitation({
        callees: [{ userID: callee, userName: "user_" + callee }],
        callType: callType,
        timeout: 60,
      })
      .then((res) => {
        console.warn(res);
        if (res.errorInvitees.length) {
          alert("The user dose not exist or is offline.");
        }
      })
      .catch((err) => {
        console.error(err);
      });
  }
```

- Remember to delete React.Strict mode in index.js file. Because if you not, useEffect will call 2 times, leading to a bug.

![Delete react strict mode to prevent bug](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zl941vr5zl5nguheopc.png)

Here is the result:
![The result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3zq7u0g6goz8wds39q4c.gif)

Github repositories: https://github.com/hqdung99/video-call-invitation

And that is it.

I think this platform is very useful. It helps me to build a video call application with a very little amount of code to write. Documentation is easy to understand, and examples and live coding are available.

ZegoCloud has many other features and it supports various platforms, languages, libraries, and frameworks (Android, IOS, flutter, ReactJS, Angular ...)

I think startups can try UI KIT to build MVP products quickly and with SDK you can deep dive to customize it.

You can learn more from ZegoCloud website and documentation: https://www.zegocloud.com/
- Sign up for 10,000 free mins monthly: https://bit.ly/3yXsodf
- Find out more about ZEGOCLOUD: http://bit.ly/3LqKuLY
- How to make video call app: https://bit.ly/3Ft8Lx5


ZEGOCLOUD allows you to easily build your live video chat apps within minutes.

Refer: https://docs.zegocloud.com/article/15385