DEV Community

glocore for Metamodal

Posted on • Updated on

Add Jitsi Meet to your React App

Step 1: Create a container for Jitsi

The Jitsi iframe needs a container element of a pre-defined height and width to render into.

import React from "react";

const VideoConference = () => {
  const jitsiContainerId = "jitsi-container-id";

  return <div id={jitsiContainerId} style={{ height: 720, width: "100%" }} />;
};

export default VideoConference;
Enter fullscreen mode Exit fullscreen mode

Step 2: Load the Jitsi Meet API Library Script

Unfortunately, this isn't available as an NPM module, and so we're gonna have to go old-school here. We first create a <script/> element with its src pointing to the source of the API library. We then append this to the document's body.

The script takes an onload callback, which runs once the script has been loaded and executed. In order to convert this into a promise, we pass it the resolve method of an empty promise.

const VideoConference = () => {
  // const jitsiContainerId = ...

  const loadJitsiScript = () => {
    let resolveLoadJitsiScriptPromise = null;

    const loadJitsiScriptPromise = new Promise((resolve) => {
      resolveLoadJitsiScriptPromise = resolve;
    });

    const script = document.createElement("script");
    script.src = "https://meet.jit.si/external_api.js";
    script.async = true;
    script.onload = resolveLoadJitsiScriptPromise
    document.body.appendChild(script);

    return loadJitsiScriptPromise;
  };

  // return ( ... )
};
Enter fullscreen mode Exit fullscreen mode

Let me know in the comments if you have a more elegant way of promise-ifying the script loading part! 😄

Step 3: Load the Jitsi IFrame

Once the script is loaded, it adds a class named JitsiMeetExternalAPI to the global window object. Instantiating this class loads the Jitsi iframe and returns an API object, which we can later be used to customise and control the Jitsi interface.

const VideoConference = () => {
  // const jitsiContainerId = ...
  const [jitsi, setJitsi] = React.useState({});

  // const loadJitsiScript = () => { ... }

  const initialiseJitsi = async () => {
    if (!window.JitsiMeetExternalAPI) {
      await loadJitsiScript();
    }

    const _jitsi = new window.JitsiMeetExternalAPI("meet.jit.si", {
      parentNode: document.getElementById(jitsiContainerId),
    });

    setJitsi(_jitsi)
  };

  React.useEffect(() => {
    initialiseJitsi();

    return () => jitsi?.dispose?.();
  }, []);

  // return ( ... )
};
Enter fullscreen mode Exit fullscreen mode

Our initialiseJitsi function is called only once when the component is first rendered, and Jitsi's dispose() method is called when the component is destroyed.

Good!

This should give you a barebones setup. Here's a CodeSandbox with what we've done so far.

Configure Jitsi

There are quite a few options to configure your Jitsi iframe. For example, if you are rolling your own Jitsi server, you can specify its URL endpoint instead of meet.jit.si. The object from instantiating JitsiMeetExternalAPI also provides quite a few methods and event listeners to configure and control the Jitsi interface. Check out Jitsi's docs for all the options, methods and events available.

Top comments (4)

Collapse
 
ericwooley profile image
Eric Wooley

Great, thanks for the post!

Let me know in the comments if you have a more elegant way of promise-ifying the script loading part! 😄

here is a suggestion for simplifying your promise a bit

const VideoConference = () => {
  // const jitsiContainerId = ...

  const loadJitsiScript = () => 
     new Promise((resolve) => {
      const script = document.createElement("script");
      script.src = "https://meet.jit.si/external_api.js";
      script.async = true;
      script.onload = resolve
      document.body.appendChild(script);
    });

  // return ( ... )
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ingsoto83 profile image
Ing. Alejandro Soto Treviño

Awesome!, you saved my day...

Collapse
 
robertio4 profile image
Roberto Rodríguez Fernández

Thanks for the tutorial.

Only one thing would change and that is the way to access the container element. Wouldn't it be more elegant to use the 'useRef' hook?

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more