Hello. When using reagent components (say, I'm using the form with r/create-class
), how to bind custom event handlers (e.g. I have :clickHandler (fn [event] (this-as t t))
and want this
to be the element here, not Window
)?
Should I do (.bind ...)
on :component-did-mount
or in some other place?
Don't know what the rest of your code looks like, but if possible I would use ref
instead of this
.
what do you want to do in your click handler that requires this
?
Usually there is no reason to make the event handlers class methods with Reagent, like is common in React. Just create handler fn in let binding. Anyway, the first parameter of class methods is going to be the component instance. Then you can ask the dom node from that. (This doesn't work for custom methods, just built-in methods)
And using ref
instead of checking component instance for dom node is highly recommended by React now.
Yeah, was just about to quote it: "If you have absolutely no control over the child component implementation, your last option is to use findDOMNode(), but it is discouraged and deprecated in StrictMode [in favor of refs]."
@lilactown read props
@lilactown i.e. when a menu isn't open, then don't close it. I thought that as a way to avoid menu instantly closing on my click
event
@juhoteperi @p-himik so that should be function refs right? I.e. not React.createRef()
but sth more old?
is there a reason you’re use r/create-class
?
You can use createRef
if it would work in your case. Hard to say anything based on a general description.
I don’t think you want to use refs here
well. what I want is that when I click outside of menu it closes (also possibly with CSSTransition from react-transition-group
)
and lifecycle methods I need to add/remove click
event listener on whole document element
gotcha. that makes sense
like juhoteperi said, you should create the handler in a let binding before you create the class. then pass in the props you need to give to the click handler in the reagent-render
function
(defn my-component
(let [click-handler (fn [event thing1 thing2]
;; do stuff with event and thing1 and thing2
)]
(r/create-class
{:reagent-render
(fn [thing1 thing2]
[:button {:on-click #(click-handler % thing1 thing2)} "click me"])})))
well, but that's a click handler for whole document, not for a button
I’m talking about your original question, about how to access this
inside an event handler to get props
thanks for suggestion, but yes, I wanted to get props inside of a handler for click
on document
I see
component-did-mount
and component-will-unmount
both receive this
as an argument
yes, I tried that, but then it somehow didn't work
i.e.
`(js/document.addEventListener "click" (.bind (aget this "clickHandler") this))`
and clickHandler
still received event
as first arg, and Window
as this
(the way to get this
in a 1st place is (this-as t t)
)
lifecycle handlers inside r/create-class
get passed this
as the first argument
yes
that's how I got it
(js/document.addEventListener
"click"
(.bind (aget this "clickHandler") this))
this code is inside of my :component-did-mount
sorry, I was confused by what you said using this-as
. you mean you’re using this-as
inside the clickHandler
yes, I did use this-as
in a clickHandler
(let [click-handler (fn [component event]
(let [props (r/props component)]
,,,))]
(r/create-class
{:component-did-mount
(fn [this]
(let [bound-click-handler #(click-handler this %)]
(set! (.-clickHandler this) bound-click-handler)
(js/document.addEventListener
"click"
bound-click-handler)))
:component-will-unmount
(fn [this]
(js/document.removeEventListener
"click"
(.-clickHandler this)))
,,,}))
let's see
yes, that works!
perhaps the last thing would be remove'ing the correct function
i.e. wrapped one
it should be removing the correct one
that’s why I (set! (.-clickHandler this) bound-click-handler)
aha
and then remove (.-clickHandler this)
in component-will-unmount
yes sure! so the only "mystery" here is why (.bind ...)
didn't work
I’m not sure, I’d have to see the rest of the code you had. this
can get quirky when mixing react/reagent/JS code
ok good to know. thanks for help @lilactown!
FYI what I wanted to achieve is mostly this: https://blog.campvanilla.com/reactjs-dropdown-menus-b6e06ae3a8fe
(but I think I'll also add transitions)
i'm a react developer, and i'm just starting to dip my feet into the world of clojure
how is the interop between JS/React libs and cljs-specific libs?
is there a preferred approach between using clojure-specific libs vs js-specific libs to solve a given problem?
routing's an example - I know and like react-router
. does it make sense to figure out how to use it in my reagent project, or is it better to come at it from the direction of clojure (e.g. using reitit
and accountant
)
interop can be a bit difficult. a lot of people opt for something that controls routing outside of react, like reitit and accountant
got it. i guess i'll bias towards a clojure-forward approach for the meantime.