React Query setQueryData在Socket.io监听器中重复添加数组元素问题求助
React Query Strict模式下消息重复添加的修复方案
问题原因
React Strict模式在开发环境中会重复执行组件副作用,如果你的socket监听没有正确清理,就会绑定两次相同的newMessage事件回调。当新消息触发时,两个回调都会调用setQueryData,导致同一条消息被添加两次。
修复方法
1. 用useEffect包裹并清理socket监听
将socket监听逻辑放到useEffect中,并在组件卸载时移除监听,避免重复绑定:
import { useEffect } from 'react'; import { useQueryClient } from '@tanstack/react-query'; // 在组件内部使用 const queryClient = useQueryClient(); useEffect(() => { const handleNewMessage = (msg) => { queryClient.setQueryData( ["chats", msg.chat], (oldChat) => { if (!oldChat) return oldChat; return { ...oldChat, messages: oldChat.messages.concat(msg) }; } ); }; // 绑定监听 socket.on("newMessage", handleNewMessage); // 清理监听:组件卸载时移除回调 return () => socket.off("newMessage", handleNewMessage); }, [queryClient]);
2. 添加消息唯一性校验(双重保险)
即使监听重复触发,也可以通过消息的唯一标识(比如msg.id)过滤重复消息:
const handleNewMessage = (msg) => { queryClient.setQueryData( ["chats", msg.chat], (oldChat) => { if (!oldChat) return oldChat; // 检查消息是否已存在 const hasDuplicate = oldChat.messages.some(message => message.id === msg.id); if (hasDuplicate) return oldChat; return { ...oldChat, messages: oldChat.messages.concat(msg) }; } ); };
3. 临时关闭Strict模式(不推荐)
如果只是快速验证问题,可以在项目入口文件(比如index.js)中移除<React.StrictMode>标签,但不建议长期使用——Strict模式能帮你提前发现很多潜在的代码问题。
验证说明
修复后,新消息只会被添加一次,重新获取聊天数据时也不会出现重复,和数据库中的数据保持一致。
内容的提问来源于stack exchange,提问作者Confucii
相关产品推荐
相关产品推荐

