Fork me on GitHub
#re-frame
<
2023-07-26
>
Ben Lieberman18:07:47

I feel like I'm doing something really stupid despite having used this pattern before: I'm adding event listeners using reg-fx like so:

(reg-fx
  :activate-buttons
  (fn [buttons]
    (doseq [button buttons]
      (.addEventListener button "click" (fn [e] (js/console.log (.. e -target -value))))))
and actioning the effect like usual, by putting the key in a map returned from a reg-event-fx. The map looks (roughly) like this: {:activate-buttons (.querySelectorAll js/document ".a-button")}. I expect this code to behave analogously to this JS
document.querySelectorAll(".a-button").forEach(button => {
  button.addEventListener("click", (e) => console.log(e.target.value))
})
For some reason I cannot determine, it does not.

p-himik18:07:51

Are there any relevant messages in the JS console?

Ben Lieberman18:07:07

None. It is seemingly a no-op. It wouldn't have anything to do with actioning this effect in my startup logic (i.e. the (dispatch-sync [:initialize-app]) ), would it?

p-himik18:07:39

Probably due to React replacing things. Or maybe something else. I would recommend two things: • Don't circumvent React - manage all the DOM properties via React (Reagent) unless you're dealing with some stateful JS library • Don't pass JS things around that you did not create. It's most pertinent to React events because they get "emptied", but DOM nodes also aren't good because they can be replaced/removed before re-frame gets a chance to handle that effect. Instead, pass the selector around and do the selecting in the handler. But not important if you handle the first item.

2
alpox06:07:14

Also, be aware that any time react decides to re-render the button you added a click event to, the click handler will be gone. Thus its always best to add event handlers through react as attribute if anyhow possible (1. Point of @U2FRKM4TW)