Next.js中Socket.io客户端事件重复触发两次的问题求助
解决Next.js中Socket.io事件触发两次的问题
核心原因
- 组件渲染时
useEffect重复绑定socket.on监听器,未在组件卸载/重新渲染时清理旧监听器。 - Next.js开发环境的Strict Mode会强制组件渲染两次,进一步导致监听器被重复注册。
解决方案
1. 给useEffect添加监听器清理逻辑
每次useEffect执行前,先移除之前绑定的同名监听器,避免重复注册:
useEffect(() => { // 单独定义监听回调函数,方便后续移除 const handleNewMessage = (data: MessageData) => { setMessages((prev: MessageData[]) => [...prev, data]) }; // 绑定监听器 socket.on("createMessage", handleNewMessage); // 组件卸载/effect重新触发时,移除对应的监听器 return () => { socket.off("createMessage", handleNewMessage); }; }, [socket]);
2. 优化Socket实例的创建(可选)
当前代码在组件外部创建Socket实例,Next.js服务器端渲染时可能出现实例复用问题,建议将初始化逻辑移到客户端组件内部:
修改socket.context.tsx:
import { createContext, FC, useContext, useEffect, useState } from "react"; import { io, Socket } from "socket.io-client"; import { getCookie } from "cookies-next"; //types interface SocketContextInterface { socket: Socket | null; } const SocketContext = createContext<SocketContextInterface>({ socket: null }); interface Props { children: React.ReactNode; } const SocketProvider: FC<Props> = (props) => { const [socket, setSocket] = useState<Socket | null>(null); useEffect(() => { // 仅在客户端初始化Socket连接 const token = getCookie("session"); const newSocket = io(process.env.NEXT_PUBLIC_WS || "http://localhost:5000", { extraHeaders: { authorization: token?.toString() || "", }, }); setSocket(newSocket); // 组件卸载时关闭Socket连接 return () => { newSocket.close(); }; }, []); return ( <SocketContext.Provider value={{ socket }}> {props.children} </SocketContext.Provider> ); }; export const useSocket = () => useContext(SocketContext); export default SocketProvider;
使用时需先判断Socket实例是否存在:
const { socket } = useSocket(); useEffect(() => { if (!socket) return; const handleNewMessage = (data: MessageData) => { setMessages((prev) => [...prev, data]); }; socket.on("createMessage", handleNewMessage); return () => socket.off("createMessage", handleNewMessage); }, [socket]);
3. 关于Strict Mode的说明
Next.js开发环境的Strict Mode是框架的调试机制,会触发两次渲染,生产环境会自动禁用。只要监听器的清理逻辑正确,生产环境不会出现事件重复触发的问题。
内容的提问来源于stack exchange,提问作者Jannat
相关产品推荐
相关产品推荐

