Я делаю приложение-галерею в React, и я застрял, потому что, когда я хочу изменить img с помощью клавиши (стрелка влево и вправо) React/browser/JS? дублирует прослушиватель, как вы можете видеть:
Код выглядит следующим образом:
const handleKey = (e) => {
console.info(`user has pressed ${e.key}`);
if (e.key === 'ArrowLeft') {
previousPicture();
}
if (e.key === 'ArrowRight') {
nextPicture();
}
};
useEffect(() => {
document.addEventListener('keydown', handleKey);
return () => window.removeEventListener('keydown', handleKey);
});
Я попытался:
Когда я пытался, например. это, приложение работало нормально, но нужно было нажать TAB, а затем использовать стрелки.
<Wrapper isOpen = {isOpen} tabIndex = {0} onKeyDown = {handleKey}>
// content...
</Wrapper>
Когда я перемещаюсь/меняю изображения кнопками, все работает хорошо.
Обновлено: Я изменил код и добавил useCallback (спасибо, добрый пользователь). «Повторяющаяся проблема» исчезла, но я не могу перемещаться со стрелками. Я пытался использовать в обратных вызовах nextPic/prevPic: [activeIndex], [] и без массива dep и все еще не работает.
Я создал песочницу: https://codesandbox.io/embed/dry-frog-tn86k2
Определите handleKey внутри функции, которую вы используете для useEffect. В противном случае каждый раз при рендеринге компонента будет создаваться новый handleKey и window.removeEventListener('keydown', handleKey) не будет иметь никакого эффекта.
использовать пустой массив зависимостей;
Если оставить массив зависимостей пустым, ожидаемого эффекта не будет, поскольку вам нужна ссылка на функцию-обработчик.
Вам придется обернуть функцию handleKey хуком useCallback, чтобы сохранить ссылку между рендерингами, поэтому очистка, которая происходит в useEffect, указывает на правильный экземпляр функции handleKey.
Примечание. Вероятно, вам также придется обернуть previousPicture и nextPicture useCallback. Зависит от того, как он инициализируется.
const handleKey = useCallback((e) => {
console.info(`user has pressed ${e.key}`);
if (e.key === 'ArrowLeft') {
previousPicture();
}
if (e.key === 'ArrowRight') {
nextPicture();
}
}, []);
useEffect(() => {
document.addEventListener('keydown', handleKey);
return () => window.removeEventListener('keydown', handleKey);
}, [handleKey]);
Я прикрепил песочницу к своему вопросу.
@ lukaasz555 Работает отлично. Вы забыли только о зависимостях для функции handleKey. [previousPicture, nextPicture]
Хахаха, ты прав! Большое спасибо за помощь! :)
Здравствуйте, у вас есть минимальный пример для вашей проблемы? Как codeandbox?