DEV Community

gugadev
gugadev

Posted on

5 1

Making Videoconferences with React and Jitsi!

Recently, in our "Product discovery" week, a new functionality raises up: Implement videoconferences inside our webapp. After some research we ended up choosing Jitsi as our tool.

The reason behind this decision were pretty solid:

  • It's open source
  • Has support for web and mobile.
  • Has plugins for frameworks like React, Angular, even Flutter.

So, before all, we needed to make a small PoC to learn about the tool and how we can implement it inside a real world application. If you need more info about Jitsi for web, please check it's repository.

The first thing we need to do is get Jitsi. Currently, there is no an official NPM package available, so, we need to use a script tag as old days. For performance reasons, we don't put the tag inside the HTML, instead, we put it inside the React component.

So, let's hands on it.


First, create a jitsi instance variable state.

import React, { useState } from "react";
const JitsiMeet = () => {
const [jitsi, setJitsi] = useState<JitsiInstance | null>(null);
return null;
}
view raw a.tsx hosted with ❤ by GitHub

Then, we need to add the script when the component mounts.

import React, { useState } from "react";
const JitsiMeet = () => {
const initialize = async () => {
const await loadScript("https://meet.jit.si/external_api.js", true);
};
useEffect(() => initialize(), []);
return null;
}
view raw b.tsx hosted with ❤ by GitHub

The loadScript function inserts the script in the body and returns a promise that will be solved after the script loads.

export function loadScript(url: string, async?: boolean): Promise<void> {
let resolver: any = null;
const onloadPromise = new Promise((resolve) => {
resolver = resolve;
});
const script = document.createElement("script");
script.src = url;
if (async) {
script.async = true;
}
script.onload = () => resolver();
document.body.appendChild(script);
return onloadPromise as Promise<void>;
}
view raw c.ts hosted with ❤ by GitHub

Once jitsi script loaded, we need to instanciate the JitsiMeetExternalAPI class with the following parameters:

  • host: url where the videoconference call is hosted.
  • params: all the params available here.

For example, we gonna use roomName and displayName. The first one is the name of the room we want to join and the second the user's mame. Note that both values will be received as props.

import React, { useState } from "react";
const JitsiMeet = ({ roomName, displayName }) => {
const [jitsi, setJitsi] = useState<JitsiInstance | null>(null);
const initialize = async () => {
const await loadScript("https://meet.jit.si/external_api.js", true);
};
const createMeet = () => {
return new window.JitsiMeetExternalAPI("meet.jit.si", {
parentNode: document.getElementById("jitsi-root"),
roomName,
userInfo: {
displayName
},
interfaceConfigOverwrite: {
SHOW_JITSI_WATERMARK: false,
SHOW_WATERMARK_FOR_GUESTS: false,
SHOW_CHROME_EXTENSION_BANNER: false,
SHOW_POWERED_BY: false,
},
configOverwrite: {
disableSimulcast: false,
},
});
};
useEffect(() => initialize(), []);
return return <div id="jitsi-root" />;
}
view raw d.tsx hosted with ❤ by GitHub

The parentNode option tell us which element will be used to insert the Jitsi iframe. So, we provided the div we are returning also.

The last step is save the JitsiMeetExternalAPI instance inside jitsi variable state and a method to destroy it once the component is unmounted.

import React, { useState } from "react";
const JitsiMeet = ({ roomName, displayName }) => {
const [jitsi, setJitsi] = useState<JitsiInstance | null>(null);
const initialize = async () => {
await loadScript("https://meet.jit.si/external_api.js", true);
setJitsi(createMeet());
};
const destroy = () => {
jitsi?.dispose();
}
const createMeet = () => {
return new window.JitsiMeetExternalAPI("meet.jit.si", {
parentNode: document.getElementById("jitsi-root"),
roomName,
userInfo: {
displayName
},
interfaceConfigOverwrite: {
SHOW_JITSI_WATERMARK: false,
SHOW_WATERMARK_FOR_GUESTS: false,
SHOW_CHROME_EXTENSION_BANNER: false,
SHOW_POWERED_BY: false,
},
configOverwrite: {
disableSimulcast: false,
},
});
};
useEffect(() => {
initialize();
return () => destroy();
}, []);
return return <div id="jitsi-root" />;
}
view raw e.tsx hosted with ❤ by GitHub

Then you just need to call the component passing the room and your name to join to a videoconference:

<JitsiMeet roomName="MyRoonName" displayName="Gus" />
Enter fullscreen mode Exit fullscreen mode

And tha'ts all! Pretty simple, right? There is a demo below to check out this code working. You need to create a meet using https://meet.jit.si and connecting using the component 😜

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more