ReactJS 和 PeerJS (simple-peer) 未捕获(在承诺中)TypeError:无法设置 null 属性(设置‘srcObject’)
我想在我的聊天网络应用中添加一个带有 WebRTC 的视频通话功能。因此,在编写代码后,我测试了代码。-> 没有视频,控制台中出现错误“未捕获(在承诺中)TypeError:无法设置 null 属性(设置'srcObject')” 屏幕截图错误消息
我的代码:
//CallProvider
import React, { createContext, useState, useRef, useEffect } from 'react';
import Peer from 'simple-peer';
import io from 'socket.io-client';
export const VideoCallContext = createContext();
const socket = io('http://localhost:5001');
export function CallProvider({ conv, id, children }) {
const videoGrid = document.querySelector('#video-grid');
const [stream, setStream] = useState(null);
const myVideoRef = useRef(null);
const peer = new Peer({
trickle: false,
stream,
});
const peers = {};
useEffect(() => {
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((currentStream) => {
setStream(currentStream);
myVideoRef.current.srcObject = currentStream.streams[0];
});
socket.on('user-connected', (userId) => {
connectToNewUser(userId, stream);
});
});
socket.on('user-disconnected', (userId) => {
if (peers[userId]) peers[userId].close();
});
function joinCall() {
peer.on('signal', (data) => {
socket.emit('join-call', {
call: conv,
userId: id,
});
});
}
function leaveCall() {
socket.emit('leave-call', {
call: conv,
userId: id,
});
navigator.mediaDevices.getUserMedia({
video: false,
audio: false,
});
}
function 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();
});
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener('loadedmetadata', () => {
video.play();
video.playsInline = true;
});
videoGrid.append(video);
}
const value = {
stream,
myVideoRef,
joinCall,
leaveCall,
};
return (
<VideoCallContext.Provider value={value}>
{children}
</VideoCallContext.Provider>
);
}
// FormCall
//use WebRTC from simplepeer
import React, { useContext } from 'react';
import { Button } from 'react-bootstrap';
import { VideoCallContext } from '../contexts/CallProvider';
export default function FormCall({ id, conv, closeWindow }) {
const { stream, myVideoRef, joinCall, leaveCall } =
useContext(VideoCallContext);
const conversation = conv;
function closeCall() {
leaveCall(id);
closeWindow();
}
return (
<>
<style>
{`
#video-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(210px, 230px));
grid-auto-rows: auto;
grid-gap: 5px;
}
`}
{`
video {
width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
object-position: center;
border-radius: 10px;
overflow: hidden;
}
`}
</style>
<div className="pb-2" id="video-grid">
<video playsInline muted ref={myVideoRef} autoPlay></video>
</div>
<div className="d-flex flex-row justify-content-around border-top pt-2">
<Button
onClick={closeCall}
className="rounded-circle position-relative"
style={{ height: '40px', width: '40px' }}
>
<i
className="bi bi-telephone-x-fill position-absolute"
style={{ left: '28%', top: '20%' }}
/>
</Button>
</div>
</>
);
}
我安装的软件包是: 软件包
我已经寻找该错误的解决方案。没有什么可以解决我的问题。
我还将“currentStream”更改为“currentStream.streams[0]”,但没有任何变化。
当您设置
const myVideoRef = useRef(null)
) 时,您将
myVideoRef.current
设置为
null
。
如果您需要在 ref 中设置
srcObject
属性:
const myVideoRef = useRef({ srcObject: null })
。
现在
myVideoRef.current.srcObject
存在并且可以设置。
尝试 const value = { stream:stream, myVideoRef:myVideoRef, joinCall:joinCall, leaveCall:leaveCall, };
另外,我会避免返回 *.Provider 本身。
像这样包装 CallProvider 及其子项:
<VideoCallContext.Provider value={Your value}>
<CallProvider >
<Child1 />
<Child2 />
</CallProvider>
</VideoCallContext.Provider>
如果您将 Context.Provider 的实例作为组件返回,则每个状态突变都会重新呈现您的 Context 。 Context 是不必要的。 如果您的 Context 完全包装了依赖的 DOM 片段,那么您的 Context 值是稳定的。
至少要更改这两者之一才能解决您的问题。
P.S. 正如 Wesley LeMahieu 发现的那样,因此我会使用 useRef() 而不是 useRef(null)。