reactjs – My React/WebRTC app is rendering multiple videos on every change
I’m creating a video chat app where users join a room via url. However, when a new user joins the video appears four times, and four times again on any change. I basically get multiple videos and userIds generated.
I’m using React frontend with Express and Peerjs.
This is my component…
import { CopyToClipboard } from "react-copy-to-clipboard";
import { Peer } from 'peerjs';
import { useParams } from 'react-router';
import "./Chaterio.css";
import io from "socket.io-client";
import styled from "styled-components";
const peer = new Peer(undefined, {
host: "https://stackoverflow.com/",
port: 9001,
})
const socket = io.connect("http://localhost:9000");
const VideoCall = () => {
const [localStream, setLocalStream] = useState(null);
const [peers, setPeers] = useState({})
const videoGridRef = useRef(null);
const myVideo = useRef();
const { roomId } = useParams();
useEffect(() => {
console.log("useEffect started...")
peer.on("open", (id) => {
socket.emit("join-room", roomId, id);
});
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
})
.then((localStream) => {
setLocalStream(localStream);
if (myVideo.current) {
myVideo.current.srcObject = localStream
myVideo.current.muted = true
};
// receive calls by listening to the on call event
peer.on('call', call => {
call.answer(localStream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream);
console.log("uservideostream ", userVideoStream)
})
});
socket.on("user-connected", (userID) => {
connectToNewUser(userID, localStream)
});
socket.on("user-disconnected", (userId) => {
console.log("user-disconnected", userId)
if (peers[userId]) peers[userId].close();
});
});
}, []);
const connectToNewUser = (userId, stream) => {
const call = peer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream);
})
call.on('close', () => {
video.remove()
})
setPeers(prevPeers => ({...prevPeers, [userId]: call}))
};
const addVideoStream = (video, stream) => {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
});
if (videoGridRef.current) {
videoGridRef.current.appendChild(video);
}
};
return (
<>
<OuterContainer>
<Header><AlinkHeader href="/">Chaterio</AlinkHeader></Header>
<Container>
<CopyToClipboard text={roomId} style={{ marginBottom: ".5rem" }}>
<Button variant="contained" color="primary" >
Copy Room Id
</Button>
</CopyToClipboard>
</Container>
<VideoContainer>
<VideoDrag >
{localStream && <video id="myVideo" draggable="true" playsInline muted ref={myVideo} autoPlay width={500} height={500} />}
</VideoDrag>
<div id="video-grid" ref={videoGridRef} />
</VideoContainer>
<SectionOuterButtons>
<SectionInnerButtons>
<a href="/"><RoomButton>Leave Room</RoomButton></a>
<a href="/room"><RoomButton>Join Room</RoomButton></a>
</SectionInnerButtons>
</SectionOuterButtons>
</OuterContainer>
</>
);
};
This is my server…
const express = require('express')
const app = express()
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server);
app.use(express.static('public'))
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.to(roomId).emit('user-connected',
userId)
socket.on('disconnect', () => {
socket.to(roomId).emit('user-disconnected',
userId)
})
})
})
server.listen(3000)
…and I create the room id with uuid as follows…
import React, { useCallback } from "react";
import styled from "styled-components";
import { useNavigate } from 'react-router-dom';
const { v4: uuidV4 } = require('uuid')
const HomePage = () => {
const navigate = useNavigate();
const handleJoinRoom = useCallback(() => {
const roomId = uuidV4();
navigate(`/videocall/${roomId}`)
}, [navigate]);
return (
<ContainerHome>
<Header>Chaterio</Header>
<SectionOuterButtons>
<SectionInnerButtons>
<a href="/chaterio"><RoomButton>New Room</RoomButton></a>
<a href="/room"><RoomButton>Join Room</RoomButton></a>
</SectionInnerButtons>
</SectionOuterButtons>
<SectionSearch>
<InputField id="RoomName" name="RoomName" type="text" placeholder="Enter Room Code"></InputField>
<SubmitButton onClick={handleJoinRoom} type="submit">Start meeting</SubmitButton>
</SectionSearch>
</ContainerHome>
);
};
Read more here: Source link
