reactjs - 在功能不起作用的套接字 io 中使用 useState 更新 dom
问题描述
我有一个正在开发的视频通话反应应用程序。
我有一个基于成功的对等连接更新 dom 的功能。
在套接字 io 通道函数中接收到成功。
具体来说,我有一组对等点,当在套接字 io 通道上接收到数据时会更新它们,然后从 setState 函数更新它。从服务器调用的其他通道被调用并且 DOM 被成功重新渲染。但只有“用户加入”频道功能不会更新 DOM。检查下面的代码。
const [peers, setPeers] = useState([]);
//const [peers, setPeers, peersUpdated ] = useUpdatableState([]);
const socketRef = useRef();
const userVideo = useRef();
const peersRef = useRef([]);
.
.
.
.
function socketAndVideo(myUser){
socketRef.current = io.connect(socket_url);
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
setStreamObj(stream);
userVideo.current.srcObject = stream;
socketRef.current.emit("join room", meetingID, myUser)
socketRef.current.on("all users", users => { // peers array gets updated here
setLoading(false);
if(users && users.length > 0){
const peers = [];
users.forEach(userobj => {
var aUser = userobj.user
var socketID = userobj.socket_id
const peer = createPeer(socketID, aUser, socketRef.current.id, stream);
peersRef.current.push({
peerID: socketID,
peer,
user: aUser,
})
peers.push({
peerID: socketID,
peer,
user: aUser,
});
})
setPeers(peers)
}
})
// peers array does NOT get updated here, The problem is within this block
socketRef.current.on("user joined", payload => {
const peer = addPeer(payload.signal, payload.callerID, payload.callerUser, stream);
peersRef.current.push({
peerID: payload.callerID,
peer,
user: payload.callerUser,
})
const peerObj = {
peerID: payload.callerID,
peer,
user: payload.callerUser,
}
console.log(peerObj) // this contains the right data everytime, its not the problem.
setPeers(users => [...users, peerObj]) // DOES NOT UPDATE THE DOM
console.log("user joined call")
})
//Gets called successfully as well
socketRef.current.on("receiving returned signal", payload => {
const item = peersRef.current.find(p => p.peerID === payload.id)
item.peer.signal(payload.signal);
})
//peers array is updated successfully here
socketRef.current.on("user left", id => {
const peerObj = peersRef.current.find(p => p.peerID === id);
if(peerObj){
peerObj.peer.destroy();
setMessage(peerObj.user.name +" left the call")
setMessageVisible(true)
}
const peers = peersRef.current.filter(p => p.peerID !== id);
peersRef.current = peers;
setPeers(peers);
})
socketRef.current.on("room full", () => {
setLoading(false);
setUser(null)
setMessage("The meeting room is full. You cant join at this time")
setMessageVisible(true)
})
socketRef.current.on("joining failed", () => {
setLoading(false);
setUser(null)
setMessage("An error occurred processing those details")
setMessageVisible(true)
})
})
}
DOM 在下面
return (
<div className="main">
{
user
? <div className="container">
<div className="other-videos">
{peers && peers.map((peer) => {
if(peer.user.name !== user.name && peer.user.email !== user.email){
return (
<Video key={peer.peerID} peer={peer.peer} user={peer.user} />
);
}
})}
</div>
<div className="main-video-div">
<video className="main-video" muted ref={userVideo} autoPlay playsInline />
</div>
</div>
: <Login meeting_id={meetingID} setLoading={setLoading} setupCall={setupCall} passcode={passcode} />
}
{
loading && <Loader show={loading} />
}
{
<Message message={message} show={messageVisible} setShow={setMessageVisible} />
}
{
user ? <CallPageFooter
isPresenting={isPresenting}
stopScreenShare={stopScreenShare}
screenShare={screenShare}
isAudio={isAudio}
isVideo={isVideo}
toggleAudio={toggleAudio}
toggleVideo={toggleVideo}
disconnectCall={disconnectCall}
/>
: null
}
</div>
);
我真的试图弄清楚为什么 DOM 的重新渲染不会发生在 socket-io 通道的“用户加入”功能中。我真的看过文章来理解这个问题。我不明白为什么它不应该重新渲染。setPeers 将 DOM 重新渲染推送到队列中,并且它应该重新渲染,因为其他通道使其重新渲染。
解决方案
推荐阅读
- python-3.x - 如何将 API 请求放入 pandas 数据框中?
- sql - MS Access 查询/设计
- php - 如何从 php 中的数组中获取特定值?
- php - 注意:尝试使用对象数组获取非对象的属性
- android - 程序类型已存在:com.dropbox.core.BadResponseCodeException
- javascript - 使用 boost 模块时,Highcharts 注释不起作用
- google-sheets - 很难为这种情况创建公式
- sql - SQL Server - WHERE子句中除以零错误(即使条件除数> 0)
- ios - iOS Swift:条件绑定的初始化程序必须具有 Optional 类型,而不是 '() -> String?
- c# - 实体框架插入具有相同类型和 id 的多个导航属性的对象