samhh / fp-ts-std

The missing pseudo-standard library for fp-ts.
https://samhh.github.io/fp-ts-std/
MIT License
207 stars 27 forks source link

changes DOM.addEventListener to returning a cleanup function #171

Closed stefanoCrmg closed 1 year ago

stefanoCrmg commented 1 year ago

So I gave it a try at implementing a way of removing an event listener after adding it to a node.

A problem I ended up facing was that by definition, you can only remove an event listener from a node if you keep around a reference to the function that you added to said node.

Given that the wrapper around DOM.addEventListener expects a (e: Event) => IO<void> as the event listener to be mounted on the node but the underlying DOM implementation of addEventListener expects a (e: Event) => void before mounting the listener to the node, we first have to turn the function inside-out and execute the IO... but this means that the listener we end up mounting on the node is actually a different function from what had originally been passed to our DOM.addEventListener!

Practically speaking, this means that:

declare const someFunction: (e: Event) => IO<void>

window.addEventListener("click", _ => someFunction(_)())
window.removeEventListener("click", _ => someFunction(_)()) 
/* ^-- this will never work, the function mounted on window click is NOT someFunction */

The cleanest way I found of dealing with this problem was making it so that DOM.addEventListener also returns an IO<void> to be used to remove that same event listener. This lets me create a private reference to the "unwrapped" (e: Event) => IO<void> and thus have a consistent way of creating aremoveEventListener that will actually work.

I also thought about possibly returning just the "private" listener as IO<(e: Event) => void> but I felt like this type definition didn't really make much sense...

I guess that we could also return some sort of State to keep around all the "right" reference to the listeners that are actually being mounted on a node, but that might be more trouble than it is worth it I guess?