-
-
Notifications
You must be signed in to change notification settings - Fork 716
Beware Returning False
There is a trap when writing DOM event handlers. Notice we are talking here about DOM event handlers, not re-frame event handlers. So this page is about reagent, not really about re-frame (except for the bit at the end).
This code looks innocent enough:
:on-mouse-out #(reset! my-over-atom false)
But notice that it inadvertently returns false, and returning false means something:
-
v0.11 of React will invoke both stopPropagation() and preventDefault() on the event. Almost certainly not what you want.
-
v0.12 of React will do the same as v0.11, except it also issues a deprecation warning about false returns.
-
v0.13 of React will not interpret a false return at all.
Note: v0.11 and v0.12 of React only test explicitly for false, not falsy values. So 'nil' is a safe return value.
Below, 'handler-fn' is a macro which will stop you from inadvertently returning false in a handler.
(defmacro handler-fn
([& body]
`(fn [~'event] ~@body nil))) ;; force return nil
:on-mouse-out (handler-fn (reset! over-atom false))
:on-mouse-out (handler-fn
(reset! over-atom false) ;; notice: no need for a 'do'
(now do something else)
(.preventDefault event)) ;; notice access to the 'event'
##Summary
There are two issues to keep in mind:
- If you accidently return false in v0.11 and v0.12 you'll get an unexpected outcome (event cancellation and stopPropagation). This can be a baffling bug, and its an easy trap to fall into. Use the macro above.
- if you deliberately return false to cause event cancellation and
stopPropagation()
, be aware that it won't work in v0.13.
React code of interest: https://github.com/facebook/react/blob/0.12-stable/src/browser/eventPlugins/SimpleEventPlugin.js#L314-L317
Update: it turns out that v0.13 is the same as v0.12. No change. However, v0.14 does appear to be rewritten and will not interpret a false return at all.
Re-frame's dispatch
returns nil, making it safe to use unwrapped by handler-fn
.
This is okay:
:on-mouse-out #(dispatch [:something])
Deprecated Tutorials:
Reagent: