组件卸载后正确删除事件处理程序

时间:2019-05-13 17:58:08

标签: reactjs javascript-events

我正在尝试实现一个HOC,如果用户单击外部,它将卸载组件。这是我的HOC ClickOutsideHOC.js

import React from 'react'

const ClickOutsideHOC = props => {

const {
    callback,
    identifier
} = props

React.useEffect(() => {
    document.addEventListener('click', handleDOMClickHOC(identifier, callback))
    return () => document.removeEventListener('click', handleDOMClickHOC) //  this needs repair
}, [])

    return props.children
}

const handleDOMClickHOC = (identifier, callback) => event => {
    const elem = document.querySelector(identifier)
    if (elem && !elem.contains(event.target))
        callback(false)
}
export default ClickOutsideHOC`

这就是我使用HOC的方式。 SomeOtherComponent.js

const [toggleValue, setToggleValue] = React.useState(false)
//
//
//
{
    toggleValue ? 
    <ClickOutsideHOC
        identifier=".some-class-name"
        callback={setToggleValue}
    >
        <div className="some-class-name">
        </div>
    </ClickOutsideHOC>: ''
}

这似乎有效。问题是我不确定删除事件处理程序的过程。 handleDOMClickHOC函数正在返回一个新的函数引用,但我没有将其存储在任何地方。我认为这会导致内存泄漏。我可以在chrome调试器控制台的Event Listeners标签中看到多个处理程序已注册到DOM。如何编写此代码,以确保不会因未订阅的事件处理程序而导致内存泄漏?

2 个答案:

答案 0 :(得分:1)

因此,如果您知道需要引用才能删除侦听器,为什么不创建它呢?

import React from 'react'

const handleDOMClickHOC = (identifier, callback) => event => {
  const elem = document.querySelector(identifier)
  if (elem && !elem.contains(event.target))
    callback(false)
}

const ClickOutsideHOC = props => {

  const {
    callback,
    identifier
  } = props

  const listener = handleDOMClickHOC(identifier, callback);

  React.useEffect(() => {
    document.addEventListener('click', listener)
    return () => document.removeEventListener('click', listener)
  }, [])

  return props.children
}
export default ClickOutsideHOC`

答案 1 :(得分:0)

您只需将所有必要的参数与call绑定:

通过这种方式,您将始终将事件,参数和其他内容传递给Handler。

React.useEffect(() => {
    document.addEventListener('click', handleDOMClickHOC.call(null, identifier, callback) } )
    return () => document.removeEventListener('click', handleDOMClickHOC) //  this needs repair
}, [])