gpt4 book ai didi

reactjs - 在基于函数的组件内的 useEffect 调用中,事件监听器不会被删除

转载 作者:行者123 更新时间:2023-12-03 14:12:02 25 4
gpt4 key购买 nike

假设我们有一个带有复选框的简单的基于函数的组件。

我很好奇为什么随后添加和删除事件监听器会成功:

function Component() {
const handler = () => 123

useEffect(() => {
window.addEventListener("beforeunload", handler)
window.removeEventListener("beforeunload", handler)
}, [isChecked])
}

但是当引入条件时,例如:

function Component() {
const handler = () => 123

useEffect(() => {
isChecked
? window.addEventListener("beforeunload", handler)
: window.removeEventListener("beforeunload", handler)
}, [isChecked])
}

监听器已添加,但不再删除。

这是为什么呢?是因为我们的处理程序是在重新渲染时重新创建的吗?当处理程序移出组件时,一切都按顺序进行。

<小时/>

这里有一个演示供那些想要测试的人使用:

https://codesandbox.io/s/y8jono6yx?module=%2Fsrc%2FCheckbox.jsx

说明:

  • 下载项目文件(顶部栏菜单)
  • 在下载的文件夹中运行npm i
  • 使用 npm start 启动开发服务器

可以通过调用 getEventListeners(window) 来检索事件监听器列表 - 至少在 Chrome 中是这样。

最佳答案

问题是 handler 是每个组件渲染上的新函数。 window.removeEventListener("beforeunload", handler) 是无操作的,因为此 handler 函数从未注册为 beforeunload 监听器。

handler 应移至组件函数的范围之外:

const handler = () => 123;

export default function Checkbox() {
const [isChecked, setIsChecked] = useState(false);
useEffect(
() => {
isChecked
? window.addEventListener("beforeunload", handler)
: window.removeEventListener("beforeunload", handler);
},
[isChecked]
);
...
};

由于 handler 无法以这种方式访问​​组件函数作用域,因此可以做的事情非常有限。更传统的方法是使 useEffect 回调仅执行一次(与 componentDidMount 对应)并从 useEffect 返回一个函数(与componentWillUnmount)。由于在useEffect函数的作用域中使用了相同的handler,所以问题消失了,但另一个问题是handler不能与一起使用>useState 因为 useEffect 中使用的 handler 是在初始渲染期间定义的函数,并且 isChecked 将始终为 false 在其范围内。 useRef 可以用于此目的(a demo ):

export default function Checkbox() {
const isCheckedRef = useRef(false);
const handler = () => {
if (isCheckedRef.current)
...
};

useEffect(
() => {
window.addEventListener("beforeunload", handler);
return () => {
window.removeEventListener("beforeunload", handler);
}
},
[]
);

return (
<input
type="checkbox"
checked={isCheckedRef.current}
onChange={e => isCheckedRef.current = e.target.checked}
/>
);
}

关于reactjs - 在基于函数的组件内的 useEffect 调用中,事件监听器不会被删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53750619/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com