В документах React Hooks показано, как удалитьEventListener на этапе очистки компонента. https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect
В моем случае использования я пытаюсь удалить функцию EventListener, относящуюся к свойству состояния функционального компонента.
Вот пример, где компонент никогда не отключается, но слушатель события должен быть удален:
function App () {
const [collapsed, setCollapsed] = React.useState(true);
React.useEffect(
() => {
if (collapsed) {
window.removeEventListener('keyup', handleKeyUp); // Not the same "handleKeyUp" :(
} else {
window.addEventListener('keyup', handleKeyUp);
}
},
[collapsed]
);
function handleKeyUp(event) {
console.log(event.key);
switch (event.key) {
case 'Escape':
setCollapsed(true);
break;
}
}
return collapsed ? (
<a href="javascript:;" onClick={()=>setCollapsed(false)}>Search</a>
) : (
<span>
<input placeholder="Search" autoFocus />
<a href="javascript:;">This</a>
<a href="javascript:;">That</a>
<input placeholder="Refinement" />
</span>
);
}
ReactDOM.render(<App />, document.body.appendChild(document.createElement('div')));
(Живой образец в https://codepen.io/caqu/pen/xBeBMN)
Проблема, которую я вижу, заключается в том, что ссылка handleKeyUp
внутри removeEventListener
меняется каждый раз, когда компонент рендерится. Функция handleKeyUp
нуждается в ссылке на setCollapsed
, поэтому она должна быть заключена в App
. Перемещение handleKeyUp
внутри useEffect
также, кажется, срабатывает несколько раз и теряет ссылку на оригинал handleKeyUp
.
Как можно условно window.removeEventListener использовать React Hooks без размонтирования компонента?