我有以下反应成分
function custom_editor_styles() {
add_editor_style('editor-styles.css');
}
add_action('init', 'custom_editor_styles');
它唯一的状态是调用中使用useState钩子定义它的参与者的哈希表。
然后我正在使用useEffect来监听聊天室的套接字事件,而只是4个事件
然后在那之后,我针对服务器上执行顺序的那些事件定义4个回调处理程序
最后,我还有另一个回调函数,该函数传递给列表中的每个子参与者,以便子组件创建其rtcPeer对象后,将其发送给父对象,以将其设置在参与者的hashTable的参与者对象上。
流程类似于参与者加入会议室->调用 existingParticipants 事件->创建本地参与者并将其添加到参与者hashTable中,然后-> receveVideoAnswer 和<如屏幕快照所示,strong>候选人多次被服务器发出
状态为空的第一个事件,其后的两个事件为空,然后再次为空,此模式将不断重复一个空状态,然后以下两个是正确的,我不知道状态是怎么回事
答案 0 :(得分:1)
困难的是,您遇到了一些相互影响的问题,这使您的故障排除感到困惑。
最大的问题是您正在设置多个套接字事件处理程序。每次重新渲染时,您都在调用socket.on
,而从未调用过socket.off
。
您需要使用以下两种方法之一:
设置单个套接字事件处理程序。使用这种方法,您将为useEffect
使用一个空的依赖项数组,但这意味着您无法在效果内的任何地方引用participants
任何地方(包括所有称为由您的消息处理程序)。如果您确实引用了participants
,则将在第一次重新渲染后引用它的旧版本。
针对participants
进行的每次更改都设置一个新的套接字事件处理程序。为了使其正常工作,您需要删除以前的事件处理程序,否则您将拥有与渲染器相同数量的事件处理程序。当您有多个事件处理程序时,创建的第一个事件处理程序将始终使用participants
的第一个版本(空),第二个将始终使用participants
的第二个版本,等等。
无论哪种情况,如果您将消息处理程序移出呈现函数并显式传递其依赖项,那么我认为您将更容易理解代码的作用。
第二个选项使用起来更加灵活,因为它使得可以在participants
功能更新之外处理setParticipants
,因此,我将仅演示该选项。使用此选项,无需在setParticipants
中使用功能更新语法,但是您确实需要始终使用从useEffect
返回的清除方法来删除以前的事件处理程序。
这是第二个选项的代码(我没有尝试执行此代码,因此我不保证自己没有语法上的小问题):
const messageHandler = (message, participants, setParticipants) => {
console.log('Message received: ' + message.event);
const onExistingParticipants = (userid, existingUsers) => {
console.log('onExistingParticipants Called!!!!!');
//Add local User
const user = {
id: userid,
username: userName,
published: true,
rtcPeer: null
};
setParticipants({
...participants,
[user.id]: user
});
existingUsers.forEach(function (element) {
receiveVideo(element.id, element.name)
})
};
const onReceiveVideoAnswer = (senderid, sdpAnswer) => {
console.log('participants in Receive answer -> ', participants);
console.log('***************')
// participants[senderid].rtcPeer.processAnswer(sdpAnswer)
};
const addIceCandidate = (userid, candidate) => {
console.log('participants in Receive canditate -> ', participants);
console.log('***************');
// participants[userid].rtcPeer.addIceCandidate(candidate)
};
const receiveVideo = (userid, username) => {
console.log('Received Video Called!!!!');
//Add remote User
const user = {
id: userid,
username: username,
published: false,
rtcPeer: null
};
setParticipants({
...participants,
[user.id]: user
});
};
//Callback for setting rtcPeer after creating it in child component
const setRtcPeerForUser = (userid, rtcPeer) => {
setParticipants({
...participants,
[userid]: {...participants[userid], rtcPeer: rtcPeer}
});
};
switch (message.event) {
case 'newParticipantArrived':
receiveVideo(message.userid, message.username);
break;
case 'existingParticipants':
onExistingParticipants(
message.userid,
message.existingUsers
);
break;
case 'receiveVideoAnswer':
onReceiveVideoAnswer(message.senderid, message.sdpAnswer);
break;
case 'candidate':
addIceCandidate(message.userid, message.candidate);
break;
default:
break;
}
};
function ConferencingRoom() {
const [participants, setParticipants] = useState({});
console.log('Participants -> ', participants);
useEffect(() => {
const handler = (message) => {messageHandler(message, participants, setParticipants)};
socket.on('message', handler);
return () => {
// THIS IS THE IMPORTANT CHANGE
socket.off('message', handler);
}
}, [participants]);
return (
<div id="meetingRoom">
{Object.values(participants).map(participant => (
<Participant
key={participant.id}
participant={participant}
roomName={roomName}
setRtcPeerForUser={setRtcPeerForUser}
sendMessage={sendMessage}
/>
))}
</div>
);
}