React中useEffect空依赖仍触发两次渲染及重复请求问题
useState为何触发两次渲染?

我在useEffect的末尾使用了[]空依赖数组,按预期应该只执行一次,但数据请求却执行了两次,导致组件重复渲染。相关代码如下:
useEffect(() => { const socket = io("http://localhost:3001"); let public_key; if (roomID.length == 0) { axios .post( `${domain}/chat/publickey?is_update_key=false`, {}, { withCredentials: true } ) .then((res) => { console.log(res); public_key = res.data.detail; console.log(public_key); socket.emit("admin_room", public_key, socket.id); axios .get(`${domain}/chat/admin/${public_key}?page=1&items_per_page=5`, { withCredentials: true, }) .then((res) => { setRoomID((prev) => [...prev, res.data]); }); }) .catch((err) => { console.log(err); }); } socket.on("customer_message", (data) => {...my other socket io code return () => { socket.disconnect(); }; }, []);
问题原因及解决办法
- React 18 Strict Mode 导致的重复执行
这是最常见的原因,React 18在开发环境的Strict Mode下,会刻意重复执行useEffect、组件挂载/卸载流程,用来检测代码中潜在的内存泄漏、不一致性等问题。这种重复执行只在开发环境存在,生产环境会自动恢复正常。
如果想在开发环境验证这一点,可以暂时移除项目入口文件(比如index.js)里的<React.StrictMode>包裹,就能看到useEffect只执行一次了。
- 代码中cleanup函数的错误
你的代码里存在缩进错误:return () => {socket.disconnect();}被写在了socket.on的回调函数内部,导致useEffect没有正确返回清理函数。这会导致组件卸载时socket没有断开,当Strict Mode触发组件重新挂载时,旧的socket可能还存在,加上新的socket,可能引发额外的请求或渲染问题。
修正后的代码应该把清理函数作为useEffect的直接返回值:
useEffect(() => { const socket = io("http://localhost:3001"); let public_key; if (roomID.length == 0) { axios .post( `${domain}/chat/publickey?is_update_key=false`, {}, { withCredentials: true } ) .then((res) => { console.log(res); public_key = res.data.detail; console.log(public_key); socket.emit("admin_room", public_key, socket.id); axios .get(`${domain}/chat/admin/${public_key}?page=1&items_per_page=5`, { withCredentials: true, }) .then((res) => { setRoomID((prev) => [...prev, res.data]); }); }) .catch((err) => { console.log(err); }); } socket.on("customer_message", (data) => { // 你的socket处理逻辑 }); // 正确返回清理函数 return () => { socket.disconnect(); }; }, []);
- 额外的状态更新触发渲染
虽然useEffect只执行一次,但内部的setRoomID会触发组件渲染,如果roomID的初始值或者更新逻辑有问题,可能导致多次状态更新,但结合你说的请求执行两次,这个可能性较低,优先排查前两点。
内容的提问来源于stack exchange,提问作者boyenec
相关产品推荐
相关产品推荐

