Today I Learned
I've run into an issue a lot recently when working on a kind-of single-page application (SPA) where simply defining a click event listener on a recurring element causes it to be attached multiple times on each page navigation.
I won't bore you with the specifics of how the kind-of SPA works under the hood, but suffice it to say that I must define the event listener on the wider page(s) instead of a separate file that's loaded once.
I could check if the element already has an click event listener attached already and decide what to do based on that, or add a removeEventListener and avoid using anonymous functions in event listeners altogether so that they can be referenced later.
But, I don't like those ideas as solutions - they're bulkier and less readable. There must be a simpler way, right?
Luckily for us, addEventListener comes with an option that resolves this incredibly easily: once.
By supplying once when defining an event listener, it'll fire exactly one time and then remove itself. Simple as that.
button.addEventListener('click', () => {
toggleDialog();
}, { once: true });
If you're wondering how and why this would even be a problem in the first palce, let me give you an example:
Let's say I have a click event listener on a button that fires a toggleDialog() function. The function will first check if the dialog is open - if not, open the dialog; if so, close the dialog.
Now imagine that the button has two event listeners attached to it, as per the SPA issue I've outlined above. The first event listener calls the toggleDialog() function, sees that the dialog isn't open yet, so opens it.
But, the second event listener runs immediately, imperceptably fast, and upon calling toggleDialog() sees that the dialog is currently open, so closes it. To the user, you've clicked the button once and the dialog hasn't appeared... nightmare!
Official docs: MDN Event Listener 'once' Option
Whether you're after dev work on a brand new site, an updated design, or just have a great business idea you want to get the ball rolling on, I'm here to help. Let's collaborate together!
Start a project