Part 2: Section 2 - Building a meeting application in React with Zoom APIs and SDKs
Published: 2023-03-28 16:43:21

# Build components for Meeting Conference React Application

Up until now, we have constructed the backend and [started setting up the frontend](https://dev.to/zoom/part-2-section-1-building-a-meeting-conference-react-application-with-zoom-api-and-sdk-developer-tools-29o5). Our next step is to create the React Application components. To do so, let's first create a directory named "components" within the "src" folder, and a subdirectory within it named "hooks". The Application components will be organized into separate folders for each individual component. Each component folder will contain a JavaScript and style sheets that utilize styled components file.

In the src, run the following commands to create a components folder and hooks subdirectory folder:

```
#Working Directory : frontend/src/

cd frontend/src
mkdir components && cd components
mkdir hooks && cd hooks

touch useResource.js 
```
### hooks

We will begin by creating a custom hook that handles making requests to our backend server to retrieve information from Zoom. This approach allows us to separate the component logic and create reusable functions.

```js
import { useState, useEffect } from "react";
import axios from "axios";

export const useResource = (resourceUrl) => {
    const [resources, setResources] = useState([]);
    const [error, setError] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        (async () => {
            try {
            const response = await axios.get(resourceUrl);
            setResources(response.data);
            setLoading(false);
        } catch (err) {
            setError(err);
            setLoading(false);
        }
        })();
    }, [resourceUrl]);

    return { resources, error, loading };
};

```
___
### pages


Now we're going to make a folder called "pages". Inside that folder, we'll have separate folders for each page. First, we need to go to the "src" folder and make a new folder called "pages". Then, inside the "pages" folder, we'll make another folder called "Home": 

```js
// Working DIR: frontend/src

 cd ../ 

mkdir pages && cd pages && mkdir Home && cd Home

```

Then inside of the Home, create another folder named "Buttons":  

```js
// Working DIR: frontend/src/pages/Home

mkdir Buttons && cd Buttons

```


_____

Next, we will generate a file named "buttonComposition.js". For this component, we will employ the React component composition pattern, which involves constructing components from other components using explicitly defined props. In this instance, we will implement this pattern to attain reusable application buttons.

```js
// Working DIR: frontend/src

touch buttonComposition.js
```

### Button Composition

Add the following code to defined the styles for the buttons in our application: 

```js
// Working Directory : frontend/src/components/pages/buttons
// File: buttonComposition.js

import { HoverButton} from "../Table/TableComponents";

export const Button = ({ size, color, text, label, ...props }) => {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
      }}
    >
      <HoverButton
        style={{
          padding: "0",
          frontSize: size === "large" ? "32px" : "16px",
          background: "#316efd",
          backgroundColor: color,
          display: "grid",
          placeItems: "center",
          borderRadius: "25px",
          width: "100px",
          height: "100px",
          lineHeight: "100px",
          color: "white",
          transition: "transform 0.2s cubic-bezier(0.235, 0, 0.05, 0.95)",
        }}
        {...props}
      >
        <span style={{fontSize: "55px" }} class="material-icons md-55"> {text} </span>
      </HoverButton>

      <p> {label}</p>
    </div>
  );
};

export const OrangeButton = (props) => {
  return <Button {...props} color="#faa92f" />;
};

export const BlueButton = (props) => {
  return <Button {...props} color="#316efd" size="large" />;
};


```
____



# Embed Zoom Meeting SDK

So far we've used design patterns to achieve component  usability and make interacting with our Zoom Rest API's easier to use. Now, we're going to put Zoom Meetings and Webinars right into our React app using something called a CDN. The Zoom Meeting SDK for web has different ways to do this and we'll explore them: 

* The client view which provides the option to display the Meeting SDK for web as a full page.

* The component view which provides the option to display the Meeting SDK for web in components on your page. 

In this project, we'll use "client view" for a familiar Zoom Meeting experience. Client view is like the Zoom web client, but it's inside our own web page.

# Install Meeting SDK from CDN

To install the Meeting SDK for web via the Meeting SDK CDN, we'll need to add the following scripts and elements to the index.html found in the public folder:

1. CDN & Dependencies scripts for client view  
2. CSS styles element
3. zmmtg-root element which will handle client overlays and accessibility. 

Here is what the final index.html file looks like:

```


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">   <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->

    <title>Zoom Clone</title>
    
     <!-- Add CSS scripts for Client View -->
     <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.6.0/css/bootstrap.css" />
     <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.6.0/css/react-select.css" />

     <!-- Add Meta tag to enable SharedArrayBuffer Web SDK Gallery View and Virtual Backgrounds -->
    <meta http-equiv="origin-trial" content=%REACT_APP_MSDK_ORIGIN_TRAIL% />


   
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <div id="portal"></div>

       <!-- Add Scripts for Client View  -->
       <script src="https://source.zoom.us/2.6.0/lib/vendor/react.min.js"></script>
       <script src="https://source.zoom.us/2.6.0/lib/vendor/react-dom.min.js"></script>
       <script src="https://source.zoom.us/2.6.0/lib/vendor/redux.min.js"></script>
       <script src="https://source.zoom.us/2.6.0/lib/vendor/redux-thunk.min.js"></script>
       <script src="https://source.zoom.us/2.6.0/lib/vendor/lodash.min.js"></script>
   
        
       <script src="https://source.zoom.us/zoom-meeting-2.6.0.min.js"></script>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

```
# Manage the Zoom Meeting SDK DOM element with CSS

When imported, the Meeting SDK for Web adds new elements to the DOM to handle client overlays and accessibility elements. To manage the Zoom Meeting SDK DOM element within the application, we need to hide the DOM element until it is needed. To do this, simply set the `display` to `none`. Otherwise, the screen will be black.

To achieve this, add the following code to the index.css file located in frontend/src/:

```
/* To hide */
#zmmtg-root {
  display: none;
}

```
______

### Add Zoom MSDK Code

After adding the Zoom Meeting SDK to the project, we can expect the ZoomMtg to be accessible in the window.To begin, let's create a folder and file for the Zoom SDK. In the 'src' directory, run the following command : 

```js
// Working DIR: frontend/src

cd ../.. && mkdir ZoomMSDK
cd ZoomMSDK && touch ZoomMSDK.js 

```
### The Zoom Meeting SDK page

We can now proceed to importing the Zoom Meeting SDK into the desired component file. This file will be responsible for performing the following tasks:

* Importing the necessary assets for the Zoom Meeting SDK dependency.

* Calling a function to obtain an SDW JWT Token that will allow for authorized use of the Zoom Meeting SDK.

* Calling a function to initialize and start/join the Zoom Meeting SDK.

To achieve this, copy and paste the code snippet provided below into the ZoomMSDK.js file:


```js
// Working Directory : frontend/src/components/pages/buttons
// File: Buttons.js


import React, {useEffect} from "react";

declare var ZoomMtg;

ZoomMtg.setZoomJSLib("https://source.zoom.us/2.6.0/lib", "/av");

ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();


function ZoomMSDK() {
// Get Zoom MSDK KEY, Signature endpoint, and leave URL environment variables
const {
  REACT_APP_ZOOM_MSDK_KEY = "",
  REACT_APP_MSDK_SIGNATURE_ENDPOINT = "",
  LEAVE_URL = "http://localhost:3000/",
 } = process.env;

 // Get the meeting number and password from the URL parameters
 const queryParams = new URLSearchParams(window.location.search);
 const mn = queryParams.get("mn");
 const pw = queryParams.get("pw");

// Assign meeting role based on user type
const role = "1"; // 1 for host, 0 for attendee


  const getSignature = (e) => {
    
    if (e) e.preventDefault();
  
    
    const SIGNATURE_OPTIONS = {
      method: "POST",
      headers: { "Content-Type": "application/json"},
      body: JSON.stringify({
        meetingNumber: mn,
        role:  parseInt(role, 10),
      }),
    };
  
    fetch(REACT_APP_MSDK_SIGNATURE_ENDPOINT, SIGNATURE_OPTIONS)
      .then((data) => data.json())
      .then(({ signature }) => !!signature && startMeeting(signature));
  };


const startMeeting = (signature) => {
  document.getElementById("zmmtg-root").style.display = "block";
  
  ZoomMtg.init({
      leaveUrl: LEAVE_URL,
      success: (success) => {
        console.log(success)
  
        ZoomMtg.join({
          signature,
          meetingNumber: mn,
          sdkKey: REACT_APP_ZOOM_MSDK_KEY,
          userName: "Your-UserName",
          passWord: pw,
          success: (success) => {
            console.log(success)
          },
          error: (error) => {
            console.log(error)
          }
        })
      },
      error: (error) => {
        console.log(error)
      }
    })
  }


useEffect(() => {
  const mn = queryParams.get("mn");
  const pw = queryParams.get("pw");
  console.log(mn, pw)
  
  
  if (mn && pw) getSignature();
  
 }, []);


  return (
    <div>zoomMSDK</div>
  )
}

export default ZoomMSDK
```

____

At this point, we have what we need to intact with Zoom REST APIs and start/join the Meeting SDK. For the second part of this section, we will focus on creating the React Application components.