与DOM交互时,是否必须使用React的useEffect Hook?
你的第二个写法看似能正常运行,但存在致命的潜在问题,useEffect在这类与外部系统交互的场景中绝非可有可无,而是保证代码健壮性的核心,原因如下:
避免重复绑定事件
组件每次渲染(比如position更新触发重渲染、父组件传递新props),都会执行window.addEventListener('pointermove', handleMove)。这意味着同一个pointermove事件会被绑定多次,每触发一次鼠标移动,handleMove就会执行N次,setPosition也会触发N次重渲染,直接造成性能浪费,甚至可能引发逻辑异常。防止内存泄漏与无效状态更新
当组件被卸载(比如路由跳转、条件渲染移除组件),你的代码没有移除pointermove监听。此时handleMove仍然会留在window的事件队列中,一旦触发鼠标移动,handleMove里的setPosition会尝试更新一个已经卸载的组件的state,直接触发React警告:"Can't perform a React state update on an unmounted component",同时造成内存泄漏。而useEffect返回的清理函数会在组件卸载或依赖项变化时自动执行,帮你移除监听,从根源避免这类问题。遵循React渲染逻辑
组件的主函数属于渲染阶段,要求是纯函数(无副作用、相同输入对应相同输出)。直接在主函数里绑定事件属于副作用操作,会破坏渲染的纯净性,在React并发渲染等复杂场景下可能引发不可预测的行为。useEffect的回调会在渲染完成后的commit阶段执行,此时DOM已经更新,副作用操作不会干扰渲染过程,完全契合React的生命周期设计。
简言之,处理事件监听、AJAX请求、定时器这类与外部系统交互的副作用时,useEffect是React官方推荐的标准方案,它帮你管理副作用的生命周期,让代码更规范、更健壮。
内容的提问来源于stack exchange,提问作者kKao4

