Чтобы очистить в useEffect, верните функцию в эффекте. Эта функция будет вызываться при каждом повторном запуске эффекта и при размонтировании компонента.
Причина, по которой это позволит правильно удалить прослушиватель событий, заключается в том, что useEffect создает замыкание над текущей версией функция handleClick
. Что позволяет функции очистки иметь ту же ссылку, чтобы ее можно было правильно очистить. В оригинале это не сработало, потому что каждый раз при повторном запуске useEffect новая версия handleClick
закрывалась, а затем с новой версией производилась очистка.
useEffect(() => {
if (!display) {
return;
}
document.addEventListener('click', handleClick);
return () => document.removeEventListener('click', handleClick);
}, [display, handleClick]);
Кроме того, вы можете сделать эффект менее частым, используя вместо этого ссылку на функцию handleClick
.
Например, в большинстве случаев это c. Хотя вы можете легко абстрагировать некоторые ссылки и дополнительный эффект использования на отдельный хук.
const handleClickRef = useRef(handleClick);
useEffect(()=>{
handleClickRef.current = handleClick;
},[handleClick])
useEffect(() => {
if (!display) {
return;
}
const funct = (evt)=>handleClickRef.current(evt);
document.addEventListener('click',funct);
return () => document.removeEventListener('click', funct);
}, [display]);