Express+React+Socket.io开发中服务端socket.on事件无明显原因触发两次
问题根因
- 核心错误是在Reducer函数中执行了socket.emit这类副作用操作,Reducer的设计原则是必须为纯函数:相同的输入永远返回相同的输出,不能包含任何修改外部变量、发起网络请求、触发IO操作等副作用逻辑。
- React 18 及以上版本默认开启开发环境严格模式(
<StrictMode>),该模式下会故意重复调用Reducer两次,目的是校验开发者编写的Reducer是否符合纯函数要求,避免逻辑不纯导致的线上问题。你感知到Reducer只执行了一次,大概率是浏览器控制台开启了「重复日志合并」功能,掩盖了两次调用的日志输出。 - 事件处理函数(比如你写的
handleSubmit)不受严格模式重复调用的影响,所以把emit逻辑移到事件回调中后,只会触发一次,问题自然解决。
正确实践建议
- 所有副作用操作不要放在Reducer中处理,可选的实现方案有三种:
- 直接在用户交互的事件回调(如点击、提交事件)中执行副作用,和你调整后的写法一致
- 通过
useEffect监听相关状态的变化,状态变更后触发副作用 - 如果使用Redux等状态管理库,搭配
redux-thunk、redux-saga等副作用中间件统一处理异步/IO逻辑
内容的提问来源于stack exchange,提问作者Michael Heilemann
相关产品推荐
相关产品推荐

