Home > Enterprise >  React addEventListener duplicate listener
React addEventListener duplicate listener

Time:11-18

I am making a gallery app in React and I stucked 'cuz when I want to change img by key (left & right arrow) React/browser/JS? duplicates listener, as you can see:

console.log screen

The code looks like this:

const handleKey = (e) => {
        console.log(`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);
    });

I tried to:

When I tried e.g. this, app worked fine, but it was necessary to press TAB & then using arrows.

<Wrapper isOpen={isOpen} tabIndex={0} onKeyDown={handleKey}>
// content...
</Wrapper>

When I am navigating/changing images by buttons everything works well.

EDIT: I modified code and added useCallback (thanks kind user). The 'duplicate issue' is gone, but I can't navigate with arrows. I tried to use in nextPic/prevPic callbacks: [activeIndex], [], and no dep array and still doesn't work.

I've created sandbox: https://codesandbox.io/embed/dry-frog-tn86k2

CodePudding user response:

use empty dependencies array;

Leaving the dependency array empty will have no expected effect, since you need to have the reference to the handler function.

You'd have to wrap the handleKey function with useCallback hook to persist the reference between renders, so the cleanup that takes place in useEffect points to the right handleKey function instance.

Note: You'd probably have to wrap the previousPicture and nextPicture with useCallback as well. Depends how it is initialized.

const handleKey = useCallback((e) => {
    console.log(`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]);
  • Related