跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何正确使用 useEffect 实现鼠标跟随的自定义光标组件

本文详解将类组件改造为函数组件时,useEffect 依赖数组缺失导致的事件监听失效问题,并提供可运行的 NeonCursor 自定义光标实现方案。 本文详解将类组件改造为函数组件时,`useeffect` 依赖数组缺失导致的事件监听失效问题,并提供可运行的 neoncursor 自定义光标实现方案。 在将类组件迁移至 React 函数组件并使用 Hooks 的过程中,一个常见却隐蔽的错误是忽略了 useEffect 的依赖数组。上述代码中,NeonCursor 组件无法响应鼠标移动,根本原因在于: useEffect 缺少空依赖数组 [],导致每次状态更新都会重新注册事件监听器,而旧监听器未被及时清理,造成逻辑混乱与性能隐患 。 更关键的是,原始代码中存在两处严重类型误用: setTop({ top: event.pageY }) 和 setLeft({ left: event.pageX }) 错误地将对象传入 useState setter,但 top 和 left 是数值状态,应直接传入数字; JSX 中 style.top 和 style.left 被赋值为 setTop(函数)和 setLeft(函数),而非实际的数值状态,导致样式无效。 以下是修复后的完整、可运行代码:
function App() { const [isCustomCursor, setIsCustomCursor] = React.useState(false); const toggleCursor = () => { setIsCustomCursor(prev => !prev); }; return ( <> {isCustomCursor && } ); } function NeonCursor() { const [position, setPosition] = React.useState({ top: 0, left: 0 }); React.useEffect(() => { const handleMouseMove = (event) => { setPosition({ top: event.pageY, left: event.pageX, }); }; document.addEventListener('mousemove', handleMouseMove); document.documentElement.classList.add('no-cursor'); // 清理函数:移除监听器 + 恢复默认光标 return () => { document.removeEventListener('mousemove', handleMouseMove); document.documentElement.classList.remove('no-cursor'); }; }, []); // ✅ 关键:空依赖数组,确保仅在挂载/卸载时执行 return ( ); } ReactDOM.render(, document.getElementById('root'));
注意事项与最佳实践: ✅ 始终为只应在挂载时执行的副作用添加 [] 依赖数组 ,否则 useEffect 会在每次渲染后重新运行,引发重复绑定、内存泄漏或状态竞争; ✅ 使用单一状态对象(如 { top, left })管理关联数据,比分散的 useState 更易维护且避免竞态; ✅ 在 style 中直接使用解构后的数值(position.top),切勿传入 setter 函数; ✅ 添加 transform: 'translate(-50%, -50%)' 可使光标图像中心精准对齐鼠标位置(需确保图片尺寸固定); ⚠️ 若项目使用 CSS-in-JS 或全局样式,请确保 .no-cursor { cursor: none; } 已正确定义。 通过规范使用 useEffect 并修正状态更新逻辑,即可稳定实现高性能、可复用的函数式自定义光标组件。

相关文章