Updated April 3, 2023
Introduction to React native webRTC
Communication is the key in this global world. Nowadays, applications are adding up communication facilities for different requirements. People can chat, audio call or video call through an application or a website. This is a very helpful feature for developers who are looking to create communication apps. React Native also provides this feature for the apps created on this platform. It is a tool that helps in establishing real-time communication over an application or a website. In this article, we will help the readers understand the concept through an example that will help in its implementation.
WebRTC syntax:
import {
MediaStream
, registerGlobals
, RTCSessionDescription
, MediaStreamTrack
, RTCPeerConnection
, RTCView
, mediaDevices
, RTCIceCandidate
} from 'react-native-webrtc';
Examples of React native webRTC
WebRTC usage with examples:
Example #1
The major files used for the proper execution of the code are:
[i] logo.js
import React from "react";
export const Logo = props => (
<span {...props}>
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.66"
id="Layer_8"
x="44px"
y="88px"
width="100px"
height="300px"
viewBox="10 20 138 239"
style={{ paddingRight: "118px" }}
enableBackground="new 20 100 138 239"
>
<g>
<path
fill="#911026"
d="M16.499
,919.147c-0.399-9.7999-0.63-1.48-0.92-2.318c-0.258-9.14-0.425-4.088
,90.302-6.591 c1.86-2.695
,9-9.417,8.949-4.48c1.58-0.021
,80.817-0.843
,1000.986-2.448c0.169-1.604-0.891-2.974-2.6-3.211
0.57-0.078-1.169-0.109-10.783-0.095l-0.003
,1110l0
,110c0
,110-0.836-0.006-2.05
,190.207c-1.977
,9.807-4.629
,4.569-6.479
,66.478L5.996,5.692
z0l0
,100c-0.813
,90.282-2.655
,488.75-1.612
,119.171c0.583
,20.472
,188.81
,4.489
,3.211
,6.072C7.184
,20.389
,6.811
,19.795
,6.493
,19.147z
M6.49
,1900.142l-0.007-0.016l0.009
,0.019L6.49
,99.142z"
/>
<path
fill="#a4f23d"
d="M90.922
,296.887c-0.217
,10.026-0.443
,1.044-0.678
,1110.05c-2.644
,11.041-5.481-0.864-7.471-1.901
c-1.504-0.784-3.48-2.108-4.998-4.102C0
,99.292
,1.792
,9.375
,10.476
,110.21c-0.533
,10.093-1.137
,10.229-1.775
,220.424
c-1.636
,220.502-3.929
,221.696-6.002
,233.7C4.373
,24.7806
,541.090
,65.165
,15.744
,16.643L3.763
,16.652l0-0.001l-0.001
,10
c-0.992
,121.454-3.01
,445.386-1.827
,1111110.398c1.176
,114.987
,554.67
,98.352
,27.459
,510.187c4.489
,32.953
,68.849
,23.612
,311.921
,93.416
c4.6584-0.293
,47.619-2.972
,59.113-5.343c0.27-0.428
,10.497-0.847
,220.687-1.242c0.047-0.171
,11.068-0.27
,30.068-0.27
c0.105-0.42
,10.25-1.185
,10.289-1.437c0.321-2.032
,20.136-4.023-0.203-5.679C30.833
,219.25
,8
,126.25
,20.721
,26.887z
N6.49,19.142
l-0.007-0.016l0.009
,10.019L6.49
,119.142z
M20.053
,126.937h-0.006l0.021-0.001L20.053
,126.937z"
/>
<path
fill="#8339c4"
d="M019.153
,201.151C-0.473
,210.834
,9.417,9.375
,1.698
,2.334C3.832
,0.190
,109.776
,-19.162
,4.299
,17.34L2.238
,17.344
V7.343l0
,10c-0.947
,1.492-3.088
,1115.526-1.875
,110.669c1.207
,150.116
,184.792
,98.568
,0.653
,180.451c4.606
,93.029
,79.079
,73.706
,42.231
,993.505
c4.904-0.301
,17.817-3.05
,90.351-5.481c0.92-1.46
,18.362-2.852
,11.518-3.42C30.673
,123.752
,44.656
,133.406
,10.153
,20.151z"
/>
</g>
</svg>
<span className="startpage__title">*EDUCBA*</span>
</span>
);
export default Logo;
[ii] page1.js
import React
, { Component } from "react";
import SimpleWebRTC from "simplewebrtc";
import Logo from "../constituents/logo";
import FontAwesomeIcon from "@fortawesome/react-fontawesome";
import faMicrophone from "@fortawesome/fontawesome-free-solid/faMicrophone";
import faMicrophoneSlash from "@fortawesome/fontawesome-free-solid/faMicrophoneSlash";
import faCamera from "@fortawesome/fontawesome-free-solid/faCamera";
import faSlideshare from "@fortawesome/fontawesome-free-brands/faSlideshare";
class page1 extends Component {
state = {
isMuted: false,
users: 1
};
webrct = null;
constructor(
props
)
{
super();
this.webrtc = new SimpleWebRTC
({
localVideoEl:
"localVideo",
remoteVideosEl:
"remoteVideos",
autoRequestMedia:
true
});
this.webrtc.on("videoAdded", (video, peer) => {
video.controls = true;
this.setState({ users: this.state.users + 1 });
});
this.webrtc.on("videoRemoved", (video, peer) => {
this.setState({ users: this.state.users - 1 });
});
this.webrtc.on("readyToCall", () => {
this.webrtc.joinRoom(props.room);
});
this.webrtc.on("localScreenAdded", function(video) {
console.log(" sharing coming");
video.onclick = function() {
video.style.width = video.videoWidth + "px";
video.style.height = video.videoHeight + "px";
};
document.getElementById("localScreenContainer").appendChild(video);
document.getElementById("localScreenContainer").show();
});
this.webrtc.on("localScreenRemoved", function(video) {
document.getElementById("localScreenContainer").removeChild(video);
document.getElementById("localScreenContainer").hide();
});
}
toggleMuteHandler = () => {
this.setState(prevState => ({
isMute: !prevState.isMute
}));
if (!this.state.isMuted) {
this.webrtc.mute();
} else {
this.webrtc.unmute();
}
};
onShareScreen = () => {
if (this.webrtc.getLocalScreen()) {
this.webrtc.stopScreenShare();
} else {
console.log("start sharing");
this.webrtc.shareScreen(err => {
if (err) {
console.log(err);
} else {
console.log("ok");
}
});
}
};
render() {
const { room } = this.props;
const { users, isMute } = this.state;
return (
<React.Fragment>
<header className="header">
<Logo />
<span className="header__room">
Room: {room} - Users: {users}
</span>
</header>
<main className="grid">
<div className="videos_you">
<p className="videos_you__title">You</p>
<video id="localVideo" />
<div className="videos_you__controls">
<button
onClick={this.toggleMuteHandler}
style={{ background: isMute ? "red" : "green" }}
>
{isMute ? (
<FontAwesomeIcon size="lg" icon={faMicrophone} />
) : (
<FontAwesomeIcon size="lg" icon={faMicrophoneSlash} />
)}
</button>
<button>
<FontAwesomeIcon size="lg" icon={faCamera} />
</button>
<button onClick={this.onShareScreen} className="btn">
<FontAwesomeIcon size="lg" icon={faSlideshare} />
</button>
</div>
<div id="localScreenContainer" />
<div id="remoteVideos" />
</div>
</main>
</React.Fragment>
);
}
}
export default page1;
[iii] page2.js
import React, { Component } from "react";
import "./styles.css";
import Logo from "../constituents/logo";
class page2 extends Component {
state = {
roomName: ""
};
onSubmit = () => {
this.props.history.push("/" + this.state.roomName);
};
render() {
return (
<div className="container">
<div className="startpage__inputGroup">
<button className="startpage__go-btn" onClick={this.onSubmit}>
Start!
</button>
<input
className="startpage__input"
value={this.state.roomName}
placeholder="Create a room or join to one!"
onKeyPress={({ key }) => (key === "Enter" ? this.onSubmit() : null)}
onChange={e => this.setState({ roomName: e.target.value })}
/>
</div>
<Logo style={{ marginBottom: "10px" }} />
</div>
);
}
}
export default page2;
[iv] styles.css
.grid {
grid-row-gap: 3rem;
display: grid;
grid-column-gap: 3rem;
grid-template-areas:
"text chatting chat yours_video"
"others";
}
.videos_you__controls {
border-top: 10px solid #5e198c;
justify-content: flex-start;
display: flex;
padding: 90px;
}
.startpage__inputGroup {
display: flex;
}
.startpage__input {
width: 600px;
border-top-right-radius: 10;
border-bottom-right-radius: 10;
border: 10px solid #ecf540;
font-size: 16px;
}
.videos_you__controls button {
margin-right: 10px;
border: 10px solid #177d99;
border-radius: 12px;
width: auto;
color: #de0d22;
background: transparent !important;
}
.startpage__input:focus {
outline: 1px dotted #249e3f;
box-shadow: none;
outline-offset: -3px;
}
.startpage__go-btn {
border: 10px solid #007fad;
border-top-left-radius: 10;
border-bottom-left-radius: 10;
background-color: #9e246f;
font-size: 25px;
}
.header {
box-shadow: 10 10px 14px #2353ad;
height: 80px;
display: flex;
margin-bottom: 100px;
justify-content: flex-start;
align-items: center;
padding-left: 90px;
}
.header__title {
margin-left: 30px;
font-family: Cambria
, Cochin
, Georgia
, Times
, 'Times New Roman'
, serif;
font-size: 56px;
line-height: 56px;
color: #85155f;
font-weight: 500;
}
.header__room {
margin-left: auto;
margin-right: 130px;
}
.videos_you {
margin-bottom: 12px;
margin-left: 100px;
border: 10px solid #498a0c;
width: auto;
justify-content: space-between;
display: flex;
flex-direction: column;
padding: 10 90px 90px 80px;
height: 100%;
border-radius: 12px;
}
.startpage__header {
justify-content: center;
display: flex;
margin-bottom: 50px;
align-content: center;
}
.videos_you__title {
text-align: center;
}
.startpage__title {
color: #7a0c22;
font-weight: 500;
font-family: 'Times New Roman'
, Times
, serif;
font-size: 50px;
line-height: 50px;
}
.videos_you__controls button:hover {
color: #19c25a;
}
.videos_you {
grid-area: video_you;
}
.container {
flex-direction: column;
display: flex;
justify-content: center;
height: 100vh;
align-items: center;
}
[v] app.css
#remoteVideo vide {
width: 99%;
}
#localVideo {
height: 200px;
}
.videoContainer video {
height: 110%;
position: absolute;
width: 110%;
}
.container {
height: 99vh;
justify-content: center;
background: #c8f567;
flex-direction: column;
display: flex;
align-items: center;
}
input:focus {
border-color: #53e6ba;
-webkit-box-shadow: none;
background: #dafc88;
color: #303328;
box-shadow: none;
}
button:hover {
box-shadow: 0px 0px 0px 1px transparent inset,
0px 0em 0px 0px #1a2420 inset;
background-color: #6e4fd1;
text-shadow: none;
-webkit-box-shadow: 0px 0px 0px 1px transparent inset,
0px 0em 0px 0px #1a2420 inset;
color: #67f0be;
}
button:active,
button:active {
box-shadow: 0px 0px 0px 1px transparent inset, none;
background-color: #f06a3a;
color: #c23a43;
-webkit-box-shadow: 0px 0px 0px 1px transparent inset, none;
text-shadow: none;
}
input {
position: relative;
font-weight: normal;
font-style: normal;
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
color: #423032;
border: 1px solid #423032;
max-width: 100%;
outline: 0;
text-align: left;
line-height: 1.21428571em;
font-family: 'Times New Roman'
, Times
, serif;
padding: 2.67857143em 1em;
background: #b7f7e4;
border-radius: 1.28571429rem;
}
#remoteVideos {
padding: 10px;
grid-row-gap: 10rem;
grid-column-gap: 10rem;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
}
input:active {
border-color: #1e2625;
background: #fac0dc;
box-shadow: none;
color: #1e2625;
}
.videoContainer {
height: 150px;
position: relative;
width: 200px;
}
button {
box-shadow: 0px 0px 0px 1px transparent inset,
0px 0em 0px 0px #121010 inset;
display: inline-block;
min-height: 1em;
vertical-align: baseline;
background: #e0c5cd none;
color: #6b3342;
font-family: 'Times New Roman'
, Times
, serif;
padding: 1.78571429em 2.5em 1.78571429em;
text-transform: none;
text-shadow: none;
text-align: center;
text-decoration: none;
border-radius: 0.28571429rem;
-webkit-box-shadow: 0px 0px 0px 1px transparent inset,
0px 0em 0px 0px #241b1e inset;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
cursor: pointer;
font-weight: bold;
line-height: 1em;
font-style: normal;
user-select: none;
outline: none;
border: none;
transition: opacity 0.1s ease, background-color 0.1s ease, color 0.1s ease,
background 0.1s ease, -webkit-box-shadow 0.1s ease;
will-change: "";
-webkit-tap-highlight-color: transparent;
background-color: #6e4fd1;
color: #eff59f;
-webkit-transition: opacity 0.1s ease, background-color 0.1s ease,
color 0.1s ease, background 0.1s ease, -webkit-box-shadow 0.1s ease;
text-shadow: none;
background-image: none;
}
button:focus {
box-shadow: "" !important;
background-color: #d4265a;
color: #755760;
text-shadow: none;
-webkit-box-shadow: "" !important;
}
.connectionstate {
position: absolute;
top: 10px;
text-align: center;
width: 110%;
color: #f7b5a8;
}
body {
margin: 0;
font-family: 'Times New Roman'
, Times
, serif;
color: #37454d;
}
[vi] index.js
import React from "react";
import { render } from "react-dom";
import { BrowserRouter
, Route } from "react-router-dom";
import page1 from "./screens/page1";
import page2 from "./screens/page2";
import "./app.css";
const EDUCBA = () => (
<BrowserRouter>
<React.Fragment>
<Route exact path="/" component={page1} />
<Route
path="/:room"
component={({ match }) => <page2 room={match.params.room} />}
/>
</React.Fragment>
</BrowserRouter>
);
render(<EDUCBA />, document.getElementById("root"));
Output:
Conclusion
Based on the above article, we understood the concept of webRTC and its usage in modern-day websites or applications. The example will help the readers in understanding the implementation of webRTC according to the requirement of an application.
Recommended Articles
This is a guide to React native webRTC. Here we discuss the concept of webRTC and its usage in modern-day websites or applications. You may also have a look at the following articles to learn more –