在条件渲染中卸载组件时,useEffect的清理函数不会执行
我正在构建一个聊天组件,在挂载时会订阅一个 WebSocket,并应在卸载时取消订阅。useEffect中的清理函数在父组件通过条件渲染移除组件时似乎并没有执行。
我想要做的是
在 <ChatRoom /> 卸载时,取消对 WebSocket 连接的订阅。
function ChatRoom({ roomId }) {
useEffect(() => {
const socket = connectToRoom(roomId);
console.log('subscribed:', roomId);
return () => {
console.log('unsubscribed:', roomId);
socket.disconnect();
};
}, [roomId]);
return <div>Room: {roomId}</div>;
}
function App() {
const [show, setShow] = useState(true);
return (
<>
<button onClick={() => setShow(s => !s)}>toggle</button>
{show && <ChatRoom roomId="general" />}
</>
);
}
我的预期
当我点击切换按钮时,我期望在控制台看到 已取消订阅:general。
实际发生的情况
在挂载时我只看到一次 已订阅:general。清理日志从未出现,套接字保持打开状态(在网络选项卡中已验证)。
我已经尝试过
- 确认show实际上已经切换为false(在App中添加了日志)
- 已移除
<StrictMode>,以排除重复调用的行为 - 已检查connectToRoom返回的对象中包含
disconnect()
环境
- React 18.2.0
- Vite 5.0
- Chrome 122
解决方案
卸载只有在依赖项为空时才起作用吗?
[roomId] -> only unmount when roomId is changed?
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。