Skip to content

Instantly share code, notes, and snippets.

@hejld
Created November 22, 2015 19:36
Show Gist options
  • Save hejld/eaaff12a76ee42357493 to your computer and use it in GitHub Desktop.
Save hejld/eaaff12a76ee42357493 to your computer and use it in GitHub Desktop.
React Event Handling

EVENT HANDLING

First source file you should be reading when trying to understand React Event System is ReactBrowserEventEmitter.js.

ReactEventListener

First the event is captured at the top-level ReactEventListener.

  • in the main thread

API

  • setHandleTopLevel

  • setEnabled, isEnabled

  • monitorScrollValue

  • trapBubbledEvent, trapCapturedEvent

    • check if element is not null
    • return EventListener.capture with its own dispatchEvent handler
  • dispatchEvent

    • ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);

ReactBrowserEventEmitter

  • has the UML-like diagram of how the event system works
  • is under the DOM folder

ReactBrowserEventEmitter is used to attach top-level event listeners. For example: - EventPluginHub.putListener('myID', 'onClick', myFunction); - (This would allocate a "registration" of ('onClick', myFunction) on 'myID’.)

  • Uses ReactEventListener as an injectable event backend.
  • Gets handleTopLevel via ReactEventEmitterMixin
  • uses isEventSupported borrowed from Modernizr

API

  • setEnabled, isEnabled (using ReactEventListener)
  • trapBubbledEvent, trapCapturedEvent (using ReactEventListener)
  • ensureScrollValueMonitoring (using ReactEventListener)
  • listenTo
    • using isEventSupported check for correct event name (wheel vs mousewheel vs DOMMouseScroll)
    • decides if to use trapBubbledEvent vs trapCapturedEvent
    • makes sure that there is a lop level listener for each event type used in the app, it is attached on the document
    • some events are skipped (like 'submit' which don't consistently bubble)

ReactEventEmitterMixin

Under the shared folder.

API

  • handleTopLevel
    • Streams a fired top-level event to EventPluginHub where plugins have the opportunity to create ReactEvents to be dispatched.
    • EventPluginHub.extractEvents, EventPluginHub.enqueueEvents, EventPluginHub.processEventQueue

EventPluginHub

Under the shared folder.

This is a unified interface for event plugins to be installed and configured.

Event plugins can implement the following properties:

  • extractEvents {function(string, DOMEventTarget, string, object): *}
    • Required. When a top-level event is fired, this method is expected to extract synthetic events that will in turn be queued and dispatched.
  • eventTypes {object}
    • Optional, plugins that fire events must publish a mapping of registration names that are used to register listeners.
    • Values of this mapping must be objects that contain registrationName or phasedRegistrationNames.
  • executeDispatch {function(object, function, string)}
    • Optional, allows plugins to override how an event gets dispatched. By default, the listener is simply invoked.

Each plugin that is injected into EventsPluginHub is immediately operable.

PLUGINS

SimpleEventPlugin

Translate native events that doesn’t need special care into correct Synthetic Events. Throws out few Firefox specific events (key press events for function keys, right mouse clicks). Fixes click event bubbling for Mobile Safari.

ResponderEventPlugin

Foundation for Gesture Responder System.

write a bit more here...

https://facebook.github.io/react-native/docs/gesture-responder-system.html https://facebook.github.io/react-native/docs/panresponder.html

https://github.com/facebook/react-native/blob/master/Libraries/Components/ScrollResponder.js https://github.com/facebook/react-native/blob/master/Libraries/ReactNative/ReactNativeGlobalResponderHandler.js

This plugin contains a lot of documentation so go ahead and dive into its source code.

TapEventPlugin

Figures out if a touch can be considered as a tap based on the distance (number of pixels) between a touchStart and touchEnd. You can bind to tap using onTouchTap key.

EnterLeaveEventPlugin

Normalizes mouseenter and mouseleave, especially when it comes to moving mouse out of the window and back.

ChangeEventPlugin

This plugin creates an onChange event that normalizes change events across form elements. This event fires at a time when it's possible to change the element's value without seeing a flicker.

Supported elements are:

  • input (see isTextInputElement)
  • textarea
  • select

SelectEventPlugin

This plugin creates an onSelect event that normalizes select events across form elements.

This differs from native browser implementations in the following ways:

  • Fires on contentEditable fields as well as inputs.
  • Fires for collapsed selection.
  • Fires after user input.

BeforeInputEventPlugin

Create an onBeforeInput event to match http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.

This event plugin is based on the native textInput event available in Chrome, Safari, Opera, and IE. This event fires after onKeyPress and onCompositionEnd, but before onInput.

beforeInput is spec'd but not implemented in any browsers, and the input event does not provide any useful information about what has actually been added, contrary to the spec. Thus, textInput is the best available event to identify the characters that have actually been inserted into the target node.

This plugin is also responsible for emitting composition events, thus allowing us to share composition fallback code for both beforeInput and composition event types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment