feat:处理组件渲染导致重复注册事件文件

This commit is contained in:
MatrixSeven
2025-08-24 15:41:58 +08:00
parent 75825e1104
commit 6b69d35a20
3 changed files with 44 additions and 24 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import React, { useState, useEffect, useRef, useCallback } from 'react';
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { useSharedWebRTCManager } from '@/hooks/webrtc/useSharedWebRTCManager';
import { useFileTransferBusiness } from '@/hooks/webrtc/useFileTransferBusiness';
@@ -42,8 +42,9 @@ export const WebRTCFileTransfer: React.FC = () => {
const urlProcessedRef = useRef(false); // 使用 ref 防止重复处理 URL
const fileInputRef = useRef<HTMLInputElement>(null);
// 创建共享连接
// 创建共享连接 - 使用 useMemo 稳定引用
const connection = useSharedWebRTCManager();
const stableConnection = useMemo(() => connection, [connection.isConnected, connection.isConnecting, connection.isWebSocketConnected, connection.error]);
// 使用共享连接创建业务层
const {
@@ -60,7 +61,7 @@ export const WebRTCFileTransfer: React.FC = () => {
onFileListReceived,
onFileRequested,
onFileProgress
} = useFileTransferBusiness(connection);
} = useFileTransferBusiness(stableConnection);
// 加入房间 (接收模式) - 提前定义以供 useEffect 使用
const joinRoom = useCallback(async (code: string) => {

View File

@@ -342,7 +342,7 @@ export function useFileTransferBusiness(connection: WebRTCConnection) {
}
}, [updateState, connection]);
// 设置处理器
// 设置处理器 - 使用稳定的引用避免反复注册
useEffect(() => {
// 使用共享连接的注册方式
const unregisterMessage = connection.registerMessageHandler(CHANNEL_NAME, handleMessage);
@@ -352,7 +352,7 @@ export function useFileTransferBusiness(connection: WebRTCConnection) {
unregisterMessage();
unregisterData();
};
}, [handleMessage, handleData]);
}, [connection]); // 只依赖 connection 对象,不依赖处理函数
// 监听连接状态变化 (直接使用 connection 的状态)
useEffect(() => {
@@ -564,22 +564,27 @@ export function useFileTransferBusiness(connection: WebRTCConnection) {
// 发送文件列表
const sendFileList = useCallback((fileList: FileInfo[]) => {
if (!connection.isPeerConnected) {
// 检查连接状态 - 优先检查数据通道状态,因为 P2P 连接可能已经建立但状态未及时更新
const channelState = connection.getChannelState();
const peerConnected = connection.isPeerConnected;
console.log('发送文件列表检查:', {
channelState,
peerConnected,
fileListLength: fileList.length
});
// 如果数据通道已打开或者 P2P 已连接,就可以发送文件列表
if (channelState === 'open' || peerConnected) {
console.log('发送文件列表:', fileList);
connection.sendMessage({
type: 'file-list',
payload: fileList
}, CHANNEL_NAME);
} else {
console.log('P2P连接未建立等待连接后再发送文件列表');
return;
}
if (connection.getChannelState() !== 'open') {
console.error('数据通道未准备就绪,无法发送文件列表');
return;
}
console.log('发送文件列表:', fileList);
connection.sendMessage({
type: 'file-list',
payload: fileList
}, CHANNEL_NAME);
}, [connection]);
// 请求文件

View File

@@ -289,11 +289,25 @@ export function useSharedWebRTCManager(): WebRTCConnection {
case 'answer':
console.log('[SharedWebRTC] 📬 处理answer...');
if (pc.signalingState === 'have-local-offer') {
await pc.setRemoteDescription(new RTCSessionDescription(message.payload));
console.log('[SharedWebRTC] ✅ answer 处理完成');
} else {
console.warn('[SharedWebRTC] ⚠️ PeerConnection状态不是have-local-offer:', pc.signalingState);
try {
if (pc.signalingState === 'have-local-offer') {
await pc.setRemoteDescription(new RTCSessionDescription(message.payload));
console.log('[SharedWebRTC] ✅ answer 处理完成');
} else {
console.warn('[SharedWebRTC] ⚠️ PeerConnection状态不是have-local-offer:', pc.signalingState);
// 如果状态不对,尝试重新创建 offer
if (pc.connectionState === 'connected' || pc.connectionState === 'connecting') {
console.log('[SharedWebRTC] 🔄 连接状态正常但信令状态异常尝试重新创建offer');
// 这里不直接处理,让连接自然建立
}
}
} catch (error) {
console.error('[SharedWebRTC] ❌ 处理answer失败:', error);
if (error instanceof Error && error.message.includes('Failed to set local answer sdp')) {
console.warn('[SharedWebRTC] ⚠️ Answer处理失败可能是连接状态变化导致的');
// 清理连接状态,让客户端重新连接
updateState({ error: 'WebRTC连接状态异常请重新连接', isPeerConnected: false });
}
}
break;