#reactjs
#reactjs
Вопрос:
Итак, я сделал этот модальный https://codesandbox.io/s/amazing-morning-ukxp2?file=/src/components/Modal.js
Всякий раз, когда вы нажимаете клавишу esc, предполагается, что она закрывает модальный. Я добавил сообщение, которое будет отображаться при каждом нажатии esc.
Но если вы проверите консоль, она каждый раз печатает мои сообщения, кратные 2 раза, поэтому через некоторое время оно будет повторять сообщение примерно 100 раз
Это функция, на которую я ссылаюсь
function keyPress(e) {
if (e.key === 'Escape' amp;amp; showModal) {
setShowModal(false);
console.log('I pressed');
}
}
document.addEventListener('keydown', keyPress);
Я попытался поместить его в функцию useEffect и добавить ShowModal в качестве зависимости, но я не смог заставить его работать должным образом
Как бы я мог предотвратить отображение прослушивателя событий keydown так много раз в консоли, если я хочу, чтобы он запускался только при открытии модального режима и при однократном нажатии клавиши esc?
Кажется, что каждый раз, когда я повторно открываю модальный, он удваивает сообщение клавиши esc.
Ответ №1:
Вам необходимо обрабатывать прослушиватели событий (добавлять, удалять) внутри useEffect
hook:
useEffect(() => {
document.addEventListener("keydown", keyPress);
return () => document.removeEventListener("keydown", keyPress);
});
Таким образом, вы будете подписываться на keyPress
функцию в каждом жизненном цикле.
Чтобы улучшить его еще больше, вы могли бы обернуть keyPress
в useCallback hook (для запоминания функции в новых рендерах) и добавить ее в качестве зависимости:
const keyPress = useCallback(
(e) => {
if (e.key === "Escape" amp;amp; showModal) {
setShowModal(false);
console.log("I pressed");
}
},
[setShowModal, showModal]
);
useEffect(() => {
document.addEventListener("keydown", keyPress);
return () => document.removeEventListener("keydown", keyPress);
}, [keyPress]);
Комментарии:
1. когда мне нужно беспокоиться о добавлении массива в качестве зависимости? или почему вам не нужно было добавлять его в этом примере?
2. Вы правы, это простое изменение приведет к подписке на каждый жизненный цикл. Я добавил, как добавить вашу функцию в качестве зависимости и запомнить ее, чтобы не создавать ее при каждом повторном рендеринге.
Ответ №2:
useEffect(()=>{
document.addEventListener('keydown', someFunction);
}, []);
пустой массив в конце будет реагировать до тех пор, пока не будет обновлен компонент после загрузки