在基于函数的组件中的useEffect调用中未删除事件侦听器

时间:2018-12-12 20:09:13

标签: reactjs dom

想象一下,我们有一个带有复选框的基于功能的简单组件。

我很好奇为什么随后添加和删除事件侦听器成功的原因:

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来启动开发服务器

至少在Chrome中,可以通过调用getEventListeners(window)来检索事件侦听器列表。

1 个答案:

答案 0 :(得分:2)

问题在于apiVersion: extensions/v1beta1 kind: Deployment metadata: name: myDeploymentName labels: app: SomeLabel1 label2: SomeLabel2 spec: replicas: 100 strategy: type: RollingUpdate template: metadata: labels: app: SomeLabel1 label2: SomeLabel2 spec: containers: - name: myPodName image: myPod:latest imagePullPolicy: Always ports: - name: myPodPort containerPort: 8080 是每个组件渲染上的新功能。 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函数范围内使用了相同的handler,因此问题消失了,但是另一个问题是useEffect不能与handler一起使用,因为useState handler中使用的“函数”是在初始渲染期间定义的函数,useEffect在其范围内将始终为isCheckedfalse可以用于此目的(demo):

useRef