首页 > 解决方案 > 在功能不起作用的套接字 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 重新渲染推送到队列中,并且它应该重新渲染,因为其他通道使其重新渲染。

标签: reactjssocket.iosetstatereact-dom

解决方案


推荐阅读