为何useEffect清理函数移除未添加的事件监听器不报错?
为什么移除未添加的事件监听器不会报错?
先看你的代码场景:
import React from "react"; import "./style.css"; import { useState, useEffect } from 'react'; export default function App() { const [position, setPosition] = useState({ x: 0, y: 0 }); const [canMove, setCanMove] = useState(false); useEffect(() => { function handleMove(e) { setPosition({ x: e.clientX, y: e.clientY }); } if (canMove) window.addEventListener('pointermove', handleMove); return () => window.removeEventListener('pointermove', handleMove); }, [canMove]); return ( <> <label> <input type="checkbox" checked={canMove} onChange={(e) => { setCanMove(e.target.checked) } } /> The dot is allowed to move </label> <hr /> <div style={{ position: 'absolute', backgroundColor: 'pink', borderRadius: '50%', opacity: 0.6, transform: `translate(${position.x}px, ${position.y}px)`, pointerEvents: 'none', left: -20, top: -20, width: 40, height: 40, }} /> </> ); }
你遇到的情况是:首次渲染时canMove为false,useEffect没给window添加pointermove监听器;当勾选复选框把canMove改成true,useEffect重新执行前会先运行清理函数——调用window.removeEventListener('pointermove', handleMove),但之前根本没注册过这个监听器,却没有报错。
原因很直接:浏览器原生的removeEventListener API本身是容错设计。不管你要移除的监听器有没有注册过,或者是否和已注册的监听器匹配,浏览器都会直接忽略这个无效操作,不会抛出任何错误。
补充说明:每次useEffect执行时,都会创建一个全新的handleMove函数实例。但哪怕是同一个函数实例,只要没通过addEventListener注册过,调用removeEventListener也不会有问题——浏览器只会默默跳过这个无效的移除请求。
内容的提问来源于stack exchange,提问作者Indra
相关产品推荐
相关产品推荐

