Skip to content

Beware Event Handlers Returning False

JW edited this page Sep 16, 2015 · 9 revisions

There is a trap when writing DOM event handlers that might return false. (We are talking here about DOM event handlers, not re-frame event handlers.)

This code looks innocent enough:

:on-mouse-out #(reset! mouse-over-atom false)

But notice that it inadvertently returns false, and returning false means something: React will stop event propagation by invoking both stopPropagation() and preventDefault() on the event. This is almost certainly not what you want.

Furthermore, React v0.12 and 0.13 issue a deprecation warning, noting that this behavior will be ignored in a future release.

Note: the return value is tested explicitly for false, not falsy values. So 'nil' is a safe return value.

Relevant code in React v0.11, v0.12, v0.13.

Solution

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)))  ; always return nil

Usage Examples:

:on-mouse-out (handler-fn (reset! mouse-over-atom false))
:on-mouse-out (handler-fn
                (reset! mouse-over-atom false)   ; note: no need for a 'do'
                ; now do something else
                (.preventDefault event))         ; explicitly prevent event propagation

In summary, there are two issues:

  1. If you accidentally return false in v0.11, v0.12, and v0.13, you'll get an unexpected outcome (preventDefault and stopPropagation). This can be a baffling bug, and it's an easy trap to fall into. Use the macro above to always return nil.
  2. if you deliberately return false to cause event cancellation and stopPropagation(), be aware that this won't work in an (unspecified) future version. Use the macro above with an explicit call to (.preventDefault event) to get the desired behavior.
Clone this wiki locally